home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / games_d / gnuchess.zip / ZGNUCHSS.C < prev    next >
C/C++ Source or Header  |  1990-08-10  |  94KB  |  3,537 lines

  1. /*
  2.   gnuchess.c - C source for GNU CHESS
  3.  
  4.   Revision: 1990-04-18
  5.  
  6.   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
  7.   Copyright (c) 1988, 1989, 1990  John Stanback
  8.  
  9.   This file is part of CHESS.
  10.  
  11.   CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
  12.   WARRANTY.  No author or distributor accepts responsibility to anyone for
  13.   the consequences of using it or for whether it serves any particular
  14.   purpose or works at all, unless he says so in writing.  Refer to the CHESS
  15.   General Public License for full details.
  16.  
  17.   Everyone is granted permission to copy, modify and redistribute CHESS, but
  18.   only under the conditions described in the CHESS General Public License.
  19.   A copy of this license is supposed to have been given to you along with
  20.   CHESS so you can know your rights and responsibilities.  It should be in a
  21.   file named COPYING.  Among other things, the copyright notice and this
  22.   notice must be preserved on all copies.
  23. */
  24. /*
  25.   Modified to compile under Zortech's C compiler 2.0.
  26.   Changes are surrounded by #ifdefs with __ZTC__ which is
  27.   defined by the Zortech C compiler.
  28.  
  29.   Truman Collins
  30.   August 7, 1990
  31. */
  32.  
  33.  
  34. #include "gnuchess.h"
  35.  
  36. #include <ctype.h>
  37.  
  38. #ifdef MSDOS
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <time.h>
  42. #define RWA_ACC "r+b"
  43. #define WA_ACC "w+b"
  44. #else
  45. #define RWA_ACC "r+"
  46. #define WA_ACC "w+"
  47. #include <sys/param.h>
  48. #include <sys/types.h>
  49. #include <sys/times.h>
  50. #endif /* MSDOS */
  51.  
  52. /* <stdlib.h> */
  53. extern int abs (int);
  54. extern int atoi (const char *);
  55. /* <time.h> */
  56. extern long int time (long int *);
  57. /* <string.h> */
  58. extern void *memset (void *, int, size_t);
  59.  
  60. #define valueP 100
  61. #define valueN 350
  62. #define valueB 355
  63. #define valueR 550
  64. #define valueQ 1100
  65. #define valueK 1200
  66. #define ctlP 0x4000
  67. #define ctlN 0x2800
  68. #define ctlB 0x1800
  69. #define ctlR 0x0400
  70. #define ctlQ 0x0200
  71. #define ctlK 0x0100
  72. #define ctlBQ 0x1200
  73. #define ctlBN 0x0800
  74. #define ctlRQ 0x0600
  75. #define ctlNN 0x2000
  76. #define Patak(c, u) (atak[c][u] > ctlP)
  77. #define Anyatak(c, u) (atak[c][u] > 0)
  78.  
  79. #if ttblsz
  80. #define truescore 0x0001
  81. #define lowerbound 0x0002
  82. #define upperbound 0x0004
  83. #define kingcastle 0x0008
  84. #define queencastle 0x0010
  85.  
  86. struct hashval
  87. {
  88.   unsigned long key,bd;
  89. };
  90. struct hashentry
  91. {
  92.   unsigned long hashbd;
  93.   unsigned short mv;
  94.   unsigned char flags, depth;   /* char saves some space */
  95.   short score;
  96. #ifdef HASHTEST
  97.   unsigned char bd[32];
  98. #endif /* HASHTEST */
  99.  
  100. };
  101.  
  102. #ifdef HASHFILE
  103. /*
  104.   persistent transposition table.
  105.   The size must be a power of 2. If you change the size,
  106.   be sure to run gnuchess -t before anything else.
  107. */
  108. #define frehash 6
  109. #ifdef MSDOS
  110. #define filesz (1 << 11)
  111. #else
  112. #define filesz (1 << 17)
  113. #endif /* MSDOS */
  114. struct fileentry
  115. {
  116.   unsigned char bd[32];
  117.   unsigned char f, t, flags, depth, sh, sl;
  118. };
  119. /*
  120.   In a networked enviroment gnuchess might be compiled on different
  121.   hosts with different random number generators, that is not acceptable
  122.   if they are going to share the same transposition table.
  123. */
  124. unsigned long int next = 1;
  125.  
  126. unsigned int urand (void)
  127. {
  128.   next *= 1103515245;
  129.   next += 12345;
  130.   return ((unsigned int) (next >> 16) & 0xFFFF);
  131. }
  132.  
  133. void srand (unsigned int seed)
  134. {
  135.   next = seed;
  136. }
  137. #else
  138. #define urand rand
  139. #endif /* HASHFILE */
  140.  
  141. static unsigned long hashkey, hashbd;
  142. static struct hashval hashcode[2][7][64];
  143. #ifdef __ZTC__
  144. static struct hashentry *ttable;
  145. #define zttable(x,y) (ttable[((x) << 1) + (y)])
  146. #else
  147. static struct hashentry huge ttable[2][ttblsz];
  148. #endif /* __ZTC__ */
  149. #endif /* ttblsz */
  150. static short rpthash[2][256];
  151.  
  152. FILE *hashfile;
  153. struct leaf Tree[2000], *root;
  154. short TrPnt[maxdepth];
  155. short PieceList[2][16], PawnCnt[2][8];
  156. #define wking PieceList[white][0]
  157. #define bking PieceList[black][0]
  158. #define EnemyKing PieceList[c2][0]
  159. short castld[2], Mvboard[64];
  160. short svalue[64];
  161. struct flags flag;
  162. short opponent, computer, Awindow, Bwindow, dither, INCscore;
  163. long ResponseTime, ExtraTime, Level, et, et0, time0, ft;
  164. long NodeCnt, ETnodes, EvalNodes, HashCnt, FHashCnt, HashCol;
  165. short player, xwndw, rehash;
  166. struct GameRec GameList[512];
  167. short Sdepth, GameCnt, Game50, MaxSearchDepth;
  168. short epsquare, contempt;
  169. struct BookEntry *Book;
  170. struct TimeControlRec TimeControl;
  171. short TCflag, TCmoves, TCminutes, OperatorTime;
  172. const short otherside[3] =
  173. {1, 0, 2};
  174. unsigned short hint, PrVar[maxdepth];
  175.  
  176.  
  177. static short Pindex[64];
  178. static short PieceCnt[2];
  179. static short c1, c2, *atk1, *atk2, *PC1, *PC2, atak[2][64];
  180. static short mtl[2], pmtl[2], emtl[2], hung[2];
  181. static short FROMsquare, TOsquare, Zscore, zwndw;
  182. static short HasKnight[2], HasBishop[2], HasRook[2], HasQueen[2];
  183. static short ChkFlag[maxdepth], CptrFlag[maxdepth], PawnThreat[maxdepth];
  184. static short Pscore[maxdepth], Tscore[maxdepth];
  185. static const short qrook[3] =
  186. {0, 56, 0};
  187. static const short krook[3] =
  188. {7, 63, 0};
  189. static const short kingP[3] =
  190. {4, 60, 0};
  191. static const short rank7[3] =
  192. {6, 1, 0};
  193. static const short sweep[8] =
  194. {false, false, false, true, true, true, false, false};
  195. static unsigned short killr0[maxdepth], killr1[maxdepth];
  196. static unsigned short killr2[maxdepth], killr3[maxdepth];
  197. static unsigned short PV, Swag0, Swag1, Swag2, Swag3, Swag4;
  198.  
  199. static short Mwpawn[64], Mbpawn[64], Mknight[2][64], Mbishop[2][64];
  200. static short Mking[2][64], Kfield[2][64];
  201. static const short value[7] =
  202. {0, valueP, valueN, valueB, valueR, valueQ, valueK};
  203. static const short control[7] =
  204. {0, ctlP, ctlN, ctlB, ctlR, ctlQ, ctlK};
  205. static const short PassedPawn0[8] =
  206. {0, 60, 80, 120, 200, 360, 600, 800};
  207. static const short PassedPawn1[8] =
  208. {0, 30, 40, 60, 100, 180, 300, 800};
  209. static const short PassedPawn2[8] =
  210. {0, 15, 25, 35, 50, 90, 140, 800};
  211. static const short PassedPawn3[8] =
  212. {0, 5, 10, 15, 20, 30, 140, 800};
  213. static const short ISOLANI[8] =
  214. {-12, -16, -20, -24, -24, -20, -16, -12};
  215. static const short BACKWARD[16] =
  216. {-6, -10, -15, -21, -28, -28, -28, -28,
  217.  -28, -28, -28, -28, -28, -28, -28, -28};
  218. static const short BMBLTY[14] =
  219. {-2, 0, 2, 4, 6, 8, 10, 12, 13, 14, 15, 16, 16, 16};
  220. static const short RMBLTY[15] =
  221. {0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14};
  222. static const short KTHRT[36] =
  223. {0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
  224.  -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
  225.  -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80};
  226. static short KNIGHTPOST, KNIGHTSTRONG, BISHOPSTRONG, KATAK;
  227. static short PEDRNK2B, PWEAKH, PADVNCM, PADVNCI, PAWNSHIELD, PDOUBLED, PBLOK;
  228. static short RHOPN, RHOPNX, KHOPN, KHOPNX, KSFTY;
  229. static short ATAKD, HUNGP, HUNGX, KCASTLD, KMOVD, XRAY, PINVAL;
  230. static short stage, stage2, Developed[2];
  231. static short PawnBonus, BishopBonus, RookBonus;
  232. static const short KingOpening[64] =
  233. {0, 0, -4, -10, -10, -4, 0, 0,
  234.  -4, -4, -8, -12, -12, -8, -4, -4,
  235.  -12, -16, -20, -20, -20, -20, -16, -12,
  236.  -16, -20, -24, -24, -24, -24, -20, -16,
  237.  -16, -20, -24, -24, -24, -24, -20, -16,
  238.  -12, -16, -20, -20, -20, -20, -16, -12,
  239.  -4, -4, -8, -12, -12, -8, -4, -4,
  240.  0, 0, -4, -10, -10, -4, 0, 0};
  241. static const short KingEnding[64] =
  242. {0, 6, 12, 18, 18, 12, 6, 0,
  243.  6, 12, 18, 24, 24, 18, 12, 6,
  244.  12, 18, 24, 30, 30, 24, 18, 12,
  245.  18, 24, 30, 36, 36, 30, 24, 18,
  246.  18, 24, 30, 36, 36, 30, 24, 18,
  247.  12, 18, 24, 30, 30, 24, 18, 12,
  248.  6, 12, 18, 24, 24, 18, 12, 6,
  249.  0, 6, 12, 18, 18, 12, 6, 0};
  250. static const short DyingKing[64] =
  251. {0, 8, 16, 24, 24, 16, 8, 0,
  252.  8, 32, 40, 48, 48, 40, 32, 8,
  253.  16, 40, 56, 64, 64, 56, 40, 16,
  254.  24, 48, 64, 72, 72, 64, 48, 24,
  255.  24, 48, 64, 72, 72, 64, 48, 24,
  256.  16, 40, 56, 64, 64, 56, 40, 16,
  257.  8, 32, 40, 48, 48, 40, 32, 8,
  258.  0, 8, 16, 24, 24, 16, 8, 0};
  259. static const short KBNK[64] =
  260. {99, 90, 80, 70, 60, 50, 40, 40,
  261.  90, 80, 60, 50, 40, 30, 20, 40,
  262.  80, 60, 40, 30, 20, 10, 30, 50,
  263.  70, 50, 30, 10, 0, 20, 40, 60,
  264.  60, 40, 20, 0, 10, 30, 50, 70,
  265.  50, 30, 10, 20, 30, 40, 60, 80,
  266.  40, 20, 30, 40, 50, 60, 80, 90,
  267.  40, 40, 50, 60, 70, 80, 90, 99};
  268. static const short pknight[64] =
  269. {0, 4, 8, 10, 10, 8, 4, 0,
  270.  4, 8, 16, 20, 20, 16, 8, 4,
  271.  8, 16, 24, 28, 28, 24, 16, 8,
  272.  10, 20, 28, 32, 32, 28, 20, 10,
  273.  10, 20, 28, 32, 32, 28, 20, 10,
  274.  8, 16, 24, 28, 28, 24, 16, 8,
  275.  4, 8, 16, 20, 20, 16, 8, 4,
  276.  0, 4, 8, 10, 10, 8, 4, 0};
  277. static const short pbishop[64] =
  278. {14, 14, 14, 14, 14, 14, 14, 14,
  279.  14, 22, 18, 18, 18, 18, 22, 14,
  280.  14, 18, 22, 22, 22, 22, 18, 14,
  281.  14, 18, 22, 22, 22, 22, 18, 14,
  282.  14, 18, 22, 22, 22, 22, 18, 14,
  283.  14, 18, 22, 22, 22, 22, 18, 14,
  284.  14, 22, 18, 18, 18, 18, 22, 14,
  285.  14, 14, 14, 14, 14, 14, 14, 14};
  286. static const short PawnAdvance[64] =
  287. {0, 0, 0, 0, 0, 0, 0, 0,
  288.  4, 4, 4, 0, 0, 4, 4, 4,
  289.  6, 8, 2, 10, 10, 2, 8, 6,
  290.  6, 8, 12, 16, 16, 12, 8, 6,
  291.  8, 12, 16, 24, 24, 16, 12, 8,
  292.  12, 16, 24, 32, 32, 24, 16, 12,
  293.  12, 16, 24, 32, 32, 24, 16, 12,
  294.  0, 0, 0, 0, 0, 0, 0, 0};
  295.  
  296. #ifdef __ZTC__
  297. static unsigned char *history;
  298. static unsigned char *nextpos;
  299. #define znextpos(x,y,z) (nextpos[((x) << 12) + ((y) << 6) + (z)])
  300. static unsigned char *nextdir;
  301. #define znextdir(x,y,z) (nextdir[((x) << 12) + ((y) << 6) + (z)])
  302. short *distdata;
  303. #define zdistdata(x,y) (distdata[((x) << 6) + (y)])
  304. short *taxidata;
  305. #define ztaxidata(x,y) (taxidata[((x) << 6) + (y)])
  306. #else
  307. static unsigned char history[8192];
  308. static unsigned char nextpos[8][64][64];
  309. static unsigned char nextdir[8][64][64];
  310. short distdata[64][64];
  311. short taxidata[64][64];
  312. #endif /* __ZTC__ */
  313.  
  314. /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
  315.  
  316. #define taxicab(a,b) (taxidata[((a) << 6) + (b)])
  317.  
  318. static void
  319. Initialize_dist (void)
  320. {
  321.   register short a, b, d, di;
  322.  
  323. #if ttblsz
  324. #if __ZTC__
  325.   ttable  = (struct hashentry *) malloc(sizeof(struct hashentry) * 2 * ttblsz);
  326.   nextpos = (unsigned char *) malloc(sizeof(unsigned char) * 8 * 64 * 64);
  327.   nextdir = (unsigned char *) malloc(sizeof(unsigned char) * 8 * 64 * 64);
  328.   history = (unsigned char *) malloc(sizeof(unsigned char) * 8192);
  329.   distdata = (short *) malloc(sizeof(short) * 64 * 64);
  330.   taxidata = (short *) malloc(sizeof(short) * 64 * 64);
  331. #endif /* __ZTC__ */
  332. #endif /* ttblsz */
  333.   for (a = 0; a < 64; a++)
  334.     for (b = 0; b < 64; b++)
  335.       {
  336.         d = abs (column (a) - column (b));
  337.         di = abs (row (a) - row (b));
  338. #ifdef __ZTC__
  339.         ztaxidata(a,b) = d + di;
  340.         zdistdata(a,b) = (d > di ? d : di);
  341. #else
  342.         taxidata[a][b] = d + di;
  343.         distdata[a][b] = (d > di ? d : di);
  344. #endif /* __ZTC__ */
  345.       }
  346. }
  347.  
  348. const short Stboard[64] =
  349. {rook, knight, bishop, queen, king, bishop, knight, rook,
  350.  pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  351.  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  352.  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  353.  pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  354.  rook, knight, bishop, queen, king, bishop, knight, rook};
  355. const short Stcolor[64] =
  356. {white, white, white, white, white, white, white, white,
  357.  white, white, white, white, white, white, white, white,
  358.  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  359.  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  360.  black, black, black, black, black, black, black, black,
  361.  black, black, black, black, black, black, black, black};
  362. short board[64], color[64];
  363. /*
  364.   ptype is used to separate white and black pawns, like this;
  365.   ptyp = ptype[side][piece]
  366.   piece can be used directly in nextpos/nextdir when generating moves
  367.   for pieces that are not black pawns.
  368. */
  369. static const short ptype[2][8] =
  370. {
  371.   no_piece, pawn, knight, bishop, rook, queen, king, no_piece,
  372.   no_piece, bpawn, knight, bishop, rook, queen, king, no_piece};
  373. static const short direc[8][8] =
  374. {
  375.   0, 0, 0, 0, 0, 0, 0, 0,
  376.   10, 9, 11, 0, 0, 0, 0, 0,
  377.   8, -8, 12, -12, 19, -19, 21, -21,
  378.   9, 11, -9, -11, 0, 0, 0, 0,
  379.   1, 10, -1, -10, 0, 0, 0, 0,
  380.   1, 10, -1, -10, 9, 11, -9, -11,
  381.   1, 10, -1, -10, 9, 11, -9, -11,
  382.   -10, -9, -11, 0, 0, 0, 0, 0};
  383. static const short max_steps[8] =
  384. {0, 2, 1, 7, 7, 7, 1, 2};
  385. static const short nunmap[120] =
  386. {
  387.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  388.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  389.   -1, 0, 1, 2, 3, 4, 5, 6, 7, -1,
  390.   -1, 8, 9, 10, 11, 12, 13, 14, 15, -1,
  391.   -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
  392.   -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
  393.   -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
  394.   -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
  395.   -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
  396.   -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
  397.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  398.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
  399.  
  400.  
  401. void
  402. Initialize_moves (void)
  403.  
  404. /*
  405.   This procedure pre-calculates all moves for every piece from every square.
  406.   This data is stored in nextpos/nextdir and used later in the move generation
  407.   routines.
  408. */
  409.  
  410. {
  411.   short ptyp, po, p0, d, di, s, delta;
  412.   unsigned char *ppos, *pdir;
  413.   short dest[8][8];
  414.   short steps[8];
  415.   short sorted[8];
  416.  
  417.   for (ptyp = 0; ptyp < 8; ptyp++)
  418.     for (po = 0; po < 64; po++)
  419.       for (p0 = 0; p0 < 64; p0++)
  420.         {
  421. #ifdef __ZTC__
  422.           znextpos(ptyp,po,p0) = (unsigned char) po;
  423.           znextdir(ptyp,po,p0) = (unsigned char) po;
  424. #else
  425.           nextpos[ptyp][po][p0] = (unsigned char) po;
  426.           nextdir[ptyp][po][p0] = (unsigned char) po;
  427. #endif /* __ZTC__ */
  428.         }
  429.   for (ptyp = 1; ptyp < 8; ptyp++)
  430.     for (po = 21; po < 99; po++)
  431.       if (nunmap[po] >= 0)
  432.         {
  433. #ifdef __ZTC__
  434.           ppos = &znextpos(ptyp,nunmap[po],0);
  435.           pdir = &znextdir(ptyp,nunmap[po],0);
  436. #else
  437.           ppos = nextpos[ptyp][nunmap[po]];
  438.           pdir = nextdir[ptyp][nunmap[po]];
  439. #endif /* __ZTC__ */
  440.           /* dest is a function of direction and steps */
  441.           for (d = 0; d < 8; d++)
  442.             {
  443.               dest[d][0] = nunmap[po];
  444.               delta = direc[ptyp][d];
  445.               if (delta != 0)
  446.                 {
  447.                   p0 = po;
  448.                   for (s = 0; s < max_steps[ptyp]; s++)
  449.                     {
  450.                       p0 = p0 + delta;
  451.                       /*
  452.                         break if (off board) or
  453.                         (pawns only move two steps from home square)
  454.                       */
  455.                       if (nunmap[p0] < 0 || (ptyp == pawn || ptyp == bpawn)
  456.                           && s > 0 && (d > 0 || Stboard[nunmap[po]] != pawn))
  457.                         break;
  458.                       else
  459.                         dest[d][s] = nunmap[p0];
  460.                     }
  461.                 }
  462.               else
  463.                 s = 0;
  464.  
  465.               /*
  466.                 sort dest in number of steps order
  467.                 currently no sort is done due to compability with
  468.                 the move generation order in old gnu chess
  469.               */
  470.               steps[d] = s;
  471.               for (di = d; s > 0 && di > 0; di--)
  472.                 if (steps[sorted[di - 1]] == 0) /* should be: < s */
  473.                   sorted[di] = sorted[di - 1];
  474.                 else
  475.                   break;
  476.               sorted[di] = d;
  477.             }
  478.  
  479.           /*
  480.             update nextpos/nextdir,
  481.             pawns have two threads (capture and no capture)
  482.           */
  483.           p0 = nunmap[po];
  484.           if (ptyp == pawn || ptyp == bpawn)
  485.             {
  486.               for (s = 0; s < steps[0]; s++)
  487.                 {
  488.                   ppos[p0] = (unsigned char) dest[0][s];
  489.                   p0 = dest[0][s];
  490.                 }
  491.               p0 = nunmap[po];
  492.               for (d = 1; d < 3; d++)
  493.                 {
  494.                   pdir[p0] = (unsigned char) dest[d][0];
  495.                   p0 = dest[d][0];
  496.                 }
  497.             }
  498.           else
  499.             {
  500.               pdir[p0] = (unsigned char) dest[sorted[0]][0];
  501.               for (d = 0; d < 8; d++)
  502.                 for (s = 0; s < steps[sorted[d]]; s++)
  503.                   {
  504.                     ppos[p0] = (unsigned char) dest[sorted[d]][s];
  505.                     p0 = dest[sorted[d]][s];
  506.                     if (d < 7)
  507.                       pdir[p0] = (unsigned char) dest[sorted[d + 1]][0];
  508.                     /* else is already initialized */
  509.                   }
  510.             }
  511.         }
  512. }
  513.  
  514. /* hmm.... shouldn`t main be moved to the interface routines */
  515. int
  516. main (int argc, char **argv)
  517. {
  518.   short int ahead = true, hash = true;
  519.   char *xwin = 0;
  520.  
  521.   while (argc > 1 && ((argv[1][0] == '-') || (argv[1][0] == '+')))
  522.     {
  523.       switch (argv[1][1])
  524.         {
  525.         case 'a':
  526.           ahead = (argv[1][0] == '-') ? false : true;
  527.           break;
  528.         case 'h':
  529.           hash = (argv[1][0] == '-') ? false : true;
  530.           break;
  531. #if ttblsz
  532. #ifdef HASHFILE
  533.         case 't': /* create or test persistent transposition table */
  534.           {
  535.             if ((hashfile = fopen (HASHFILE, RWA_ACC)) == NULL)
  536.               hashfile = fopen (HASHFILE , WA_ACC);
  537.             if (hashfile != NULL)
  538.               {
  539.                 long i, j;
  540.                 int nr[maxdepth];
  541.                 struct fileentry n;
  542.  
  543.                 printf("Counting transposition file entries, wait!\n");
  544.                 for(i = 0; i < maxdepth; i++) nr[i] = 0;
  545.                 fseek(hashfile, 0L, SEEK_END);
  546.                 i = ftell(hashfile) / sizeof(struct fileentry);
  547.                 fseek(hashfile, 0L, SEEK_SET);
  548.                 for (j = 0; j < i; j++)
  549.                   {
  550.                     fread(&n, sizeof(struct fileentry), 1, hashfile);
  551.                     if (n.depth)
  552.                       {
  553.                         nr[n.depth]++;
  554.                         nr[0]++;
  555.                       }
  556.                   }
  557.                 printf("The file contains %d entries out of max %d\n",
  558.                        nr[0], i);
  559.                 for(j = 1; j < maxdepth; j++) printf("%d ",nr[j]);
  560.                 printf("\n");
  561.                 if (i < filesz)
  562.                   {
  563.                     printf("Filling transposition file, wait!\n");
  564.                     for(j = 0; j < 32; j++)
  565.                       n.bd[j] = 0;
  566.                     n.f = n.t = 0;
  567.                     n.flags = 0;
  568.                     n.depth = 0;
  569.                     n.sh = n.sl = 0;
  570.                     for (j = i; j < filesz; j++)
  571.                       fwrite (&n, sizeof(struct fileentry), 1, hashfile);
  572.                   }
  573.                 fclose(hashfile);
  574.               }
  575.             return(0);
  576.             break;
  577.           }
  578. #endif /* HASHFILE */
  579. #endif /* ttblsz */
  580.         case 'x':
  581.           xwin = &argv[1][2];
  582.           break;
  583.         default:
  584.           fprintf (stderr, "Usage: gnuchess [-a] [-t] [-x xwndw]\n");
  585.         }
  586.       argv++;
  587.       argc--;
  588.     }
  589.   Level = 0;
  590.   TCflag = false;
  591.   OperatorTime = 0;
  592.   if (argc == 2)
  593.     Level = atoi (argv[1]);
  594.   if (argc == 3)
  595.     {
  596.       TCmoves = atoi (argv[1]);
  597.       TCminutes = atoi (argv[2]);
  598.       TCflag = true;
  599.     }
  600.   Initialize ();
  601.   Initialize_dist ();
  602.   Initialize_moves ();
  603.   NewGame ();
  604.   GetOpenings ();
  605.  
  606.   flag.easy = ahead;
  607.   flag.hash = hash;
  608.   if (xwin)
  609.     xwndw = atoi (xwin);
  610.  
  611.   hashfile = NULL;
  612. #if ttblsz
  613. #ifdef HASHFILE
  614.   hashfile = fopen (HASHFILE, RWA_ACC);
  615. #endif /* HASHFILE */
  616. #endif  /* ttblsz */
  617.   while (!(flag.quit))
  618.     {
  619.       if (flag.bothsides && !flag.mate)
  620.         SelectMove (opponent, 1);
  621.       else
  622.         InputCommand ();
  623.       if (!(flag.quit || flag.mate || flag.force))
  624.         SelectMove (computer, 1);
  625.     }
  626. #if ttblsz
  627. #ifdef HASHFILE
  628.   if (hashfile) fclose(hashfile);
  629. #endif /* HASHFILE */
  630. #endif /* ttblsz */
  631.  
  632.   ExitChess ();
  633.   return (0);
  634. }
  635.  
  636. void
  637. NewGame (void)
  638.  
  639. /*
  640.   Reset the board and other variables to start a new game.
  641. */
  642.  
  643. {
  644.   short l, c, p;
  645.  
  646.   stage = stage2 = -1;          /* the game is not yet started */
  647.   flag.mate = flag.post = flag.quit = flag.reverse = flag.bothsides = false;
  648.   flag.force = false;
  649.   flag.hash = flag.easy = flag.beep = flag.rcptr = true;
  650.   NodeCnt = et0 = epsquare = 0;
  651.   dither = 0;
  652.   Awindow = 90;
  653.   Bwindow = 90;
  654.   xwndw = 90;
  655.   MaxSearchDepth = 29;
  656.   contempt = 0;
  657.   GameCnt = 0;
  658.   Game50 = 1;
  659.   hint = 0x0C14;
  660.   ZeroRPT ();
  661.   Developed[white] = Developed[black] = false;
  662.   castld[white] = castld[black] = false;
  663.   PawnThreat[0] = CptrFlag[0] = false;
  664.   Pscore[0] = 12000;
  665.   Tscore[0] = 12000;
  666.   opponent = white;
  667.   computer = black;
  668.   for (l = 0; l < 2000; l++)
  669.     Tree[l].f = Tree[l].t = 0;
  670. #if ttblsz
  671.   rehash = 6;
  672.   ZeroTTable ();
  673.   srand ((unsigned int) 1);
  674.   for (c = white; c <= black; c++)
  675.     for (p = pawn; p <= king; p++)
  676.       for (l = 0; l < 64; l++)
  677.         {
  678.           hashcode[c][p][l].key = (((unsigned long) urand ()));
  679.           hashcode[c][p][l].key += (((unsigned long) urand ()) << 16);
  680.           hashcode[c][p][l].bd = (((unsigned long) urand ()));
  681.           hashcode[c][p][l].bd += (((unsigned long) urand ()) << 16);
  682.           if (sizeof(long) > 4)
  683.             {
  684.               hashcode[c][p][l].key += (((unsigned long) urand ()) << 32);
  685.               hashcode[c][p][l].key += (((unsigned long) urand ()) << 48);
  686.               hashcode[c][p][l].bd += (((unsigned long) urand ()) << 32);
  687.               hashcode[c][p][l].bd += (((unsigned long) urand ()) << 48);
  688.             }
  689.         }
  690. #endif /* ttblsz */
  691.   for (l = 0; l < 64; l++)
  692.     {
  693.       board[l] = Stboard[l];
  694.       color[l] = Stcolor[l];
  695.       Mvboard[l] = 0;
  696.     }
  697.   ClrScreen ();
  698.   if (TCflag)
  699.     SetTimeControl ();
  700.   else if (Level == 0)
  701.     SelectLevel ();
  702.   InitializeStats ();
  703.   time0 = time ((long *) 0);
  704.   ElapsedTime (1);
  705.   UpdateDisplay (0, 0, 1, 0);
  706. }
  707.  
  708.  
  709. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  710.  
  711. static inline void
  712. pick (short int p1, short int p2)
  713.  
  714. /*
  715.   Find the best move in the tree between indexes p1 and p2. Swap the best
  716.   move into the p1 element.
  717. */
  718.  
  719. {
  720.   register short p, s;
  721.   short p0, s0;
  722.   struct leaf temp;
  723.  
  724.   s0 = Tree[p1].score;
  725.   p0 = p1;
  726.   for (p = p1 + 1; p <= p2; p++)
  727.     if ((s = Tree[p].score) > s0)
  728.       {
  729.         s0 = s;
  730.         p0 = p;
  731.       }
  732.   if (p0 != p1)
  733.     {
  734.       temp = Tree[p1];
  735.       Tree[p1] = Tree[p0];
  736.       Tree[p0] = temp;
  737.     }
  738. }
  739.  
  740. void
  741. SelectMove (short int side, short int iop)
  742.  
  743.  
  744. /*
  745.   Select a move by calling function search() at progressively deeper ply
  746.   until time is up or a mate or draw is reached. An alpha-beta window of -90
  747.   to +90 points is set around the score returned from the previous
  748.   iteration. If Sdepth != 0 then the program has correctly predicted the
  749.   opponents move and the search will start at a depth of Sdepth+1 rather
  750.   than a depth of 1.
  751. */
  752.  
  753. {
  754.   static short i, tempb, tempc, tempsf, tempst, xside, rpt;
  755.   static short alpha, beta, score;
  756.  
  757.   flag.timeout = false;
  758.   xside = otherside[side];
  759.   if (iop != 2)
  760.     player = side;
  761.   if (TCflag)
  762.     {
  763.       if ((TimeControl.moves[side] + 3) != 0)
  764.         ResponseTime = (TimeControl.clock[side]) /
  765.           (TimeControl.moves[side] + 3) -
  766.           OperatorTime;
  767.       else
  768.         ResponseTime = 0;
  769.       ResponseTime += (ResponseTime * TimeControl.moves[side]) / (2 * TCmoves + 1);
  770.     }
  771.   else
  772.     ResponseTime = Level;
  773.   if (iop == 2)
  774.     ResponseTime = 99999;
  775.   if (Sdepth > 0 && root->score > Zscore - zwndw)
  776.     ResponseTime -= ft;
  777.   else if (ResponseTime < 1)
  778.     ResponseTime = 1;
  779.   ExtraTime = 0;
  780.   ExaminePosition ();
  781.   ScorePosition (side, &score);
  782.   /* Pscore[0] = -score; */
  783.   ShowSidetomove ();
  784.  
  785.   if (Sdepth == 0)
  786.     {
  787. #if ttblsz
  788.       /* ZeroTTable (); */
  789. #endif /* ttblsz */
  790.       SearchStartStuff (side);
  791. #ifdef NOMEMSET
  792.       for (i = 0; i < 8192; i++)
  793.         history[i] = 0;
  794. #else
  795.       memset ((char *) history, 0, sizeof (history));
  796. #endif /* NOMEMSET */
  797.       FROMsquare = TOsquare = -1;
  798.       PV = 0;
  799.       if (iop != 2)
  800.         hint = 0;
  801.       for (i = 0; i < maxdepth; i++)
  802.         PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  803.       alpha = score - 90;
  804.       beta = score + 90;
  805.       rpt = 0;
  806.       TrPnt[1] = 0;
  807.       root = &Tree[0];
  808.       MoveList (side, 1);
  809.       for (i = TrPnt[1]; i < TrPnt[2]; i++)
  810.         pick (i, TrPnt[2] - 1);
  811.       if (Book != NULL)
  812.         OpeningBook (&hint);
  813.       if (Book != NULL)
  814.         flag.timeout = true;
  815.       NodeCnt = ETnodes = EvalNodes = HashCnt = FHashCnt = HashCol = 0;
  816.       Zscore = 0;
  817.       zwndw = 20;
  818.     }
  819.   while (!flag.timeout && Sdepth < MaxSearchDepth)
  820.     {
  821.       Sdepth++;
  822.       ShowDepth (' ');
  823.       score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  824.       for (i = 1; i <= Sdepth; i++)
  825.         killr0[i] = PrVar[i];
  826.       if (score < alpha)
  827.         {
  828.           ShowDepth ('-');
  829.           ExtraTime = 10 * ResponseTime;
  830.           /* ZeroTTable (); */
  831.           score = search (side, 1, Sdepth, -9000, score, PrVar, &rpt);
  832.         }
  833.       if (score > beta && !(root->flags & exact))
  834.         {
  835.           ShowDepth ('+');
  836.           ExtraTime = 0;
  837.           /* ZeroTTable (); */
  838.           score = search (side, 1, Sdepth, score, 9000, PrVar, &rpt);
  839.         }
  840.       score = root->score;
  841.       if (!flag.timeout)
  842.         for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
  843.           pick (i, TrPnt[2] - 1);
  844.       ShowResults (score, PrVar, '.');
  845.       for (i = 1; i <= Sdepth; i++)
  846.         killr0[i] = PrVar[i];
  847.       if (score > Zscore - zwndw && score > Tree[1].score + 250)
  848.         ExtraTime = 0;
  849.       else if (score > Zscore - 3 * zwndw)
  850.         ExtraTime = ResponseTime;
  851.       else
  852.         ExtraTime = 3 * ResponseTime;
  853.       if (root->flags & exact)
  854.         flag.timeout = true;
  855.       if (Tree[1].score < -9000)
  856.         flag.timeout = true;
  857.       if (4 * et > 2 * ResponseTime + ExtraTime)
  858.         flag.timeout = true;
  859.       if (!flag.timeout)
  860.         {
  861.           Tscore[0] = score;
  862.           if (Zscore == 0)
  863.             Zscore = score;
  864.           else
  865.             Zscore = (Zscore + score) / 2;
  866.         }
  867.       zwndw = 20 + abs (Zscore / 12);
  868.       beta = score + Bwindow;
  869.       if (Zscore < score)
  870.         alpha = Zscore - Awindow - zwndw;
  871.       else
  872.         alpha = score - Awindow - zwndw;
  873.     }
  874.  
  875.   score = root->score;
  876.   if (rpt >= 2 || score < -12000)
  877.     root->flags |= draw;
  878.   if (iop == 2)
  879.     return;
  880.   if (Book == NULL)
  881.     hint = PrVar[2];
  882.   ElapsedTime (1);
  883.  
  884.   if (score > -9999 && rpt <= 2)
  885.     {
  886.       MakeMove (side, root, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  887.       algbr (root->f, root->t, (short) root->flags);
  888.     }
  889.   else
  890.     algbr (0, 0, 0);
  891.   OutputMove ();
  892.   if (score == -9999 || score == 9998)
  893.     flag.mate = true;
  894.   if (flag.mate)
  895.     hint = 0;
  896.   if ((board[root->t] == pawn)
  897.       || (root->flags & capture)
  898.       || (root->flags & cstlmask))
  899.     {
  900.       Game50 = GameCnt;
  901.       ZeroRPT ();
  902.     }
  903.   GameList[GameCnt].score = score;
  904.   GameList[GameCnt].nodes = NodeCnt;
  905.   GameList[GameCnt].time = (short) et;
  906.   GameList[GameCnt].depth = Sdepth;
  907.   if (TCflag)
  908.     {
  909.       TimeControl.clock[side] -= (et + OperatorTime);
  910.       if (--TimeControl.moves[side] == 0)
  911.         SetTimeControl ();
  912.     }
  913.   if ((root->flags & draw) && flag.bothsides)
  914.     flag.mate = true;
  915.   if (GameCnt > 470)
  916.     flag.mate = true; /* out of move store, you loose */
  917.   player = xside;
  918.   Sdepth = 0;
  919.   fflush (stdin);
  920. }
  921.  
  922. int
  923. parse (FILE *fd, unsigned short int *mv, short int side)
  924. {
  925.   int c, i, r1, r2, c1, c2;
  926.   char s[100];
  927.   while ((c = getc (fd)) == ' ') ;
  928.   i = 0;
  929.   s[0] = (char) c;
  930.   while (c != ' ' && c != '\n' && c != EOF)
  931.     s[++i] = (char) (c = getc (fd));
  932.   s[++i] = '\0';
  933.   if (c == EOF)
  934.     return (-1);
  935.   if (s[0] == '!' || s[0] == ';' || i < 3)
  936.     {
  937.       while (c != '\n' && c != EOF)
  938.         c = getc (fd);
  939.       return (0);
  940.     }
  941.   if (s[4] == 'o')
  942.     if (side == black)
  943.       *mv = 0x3C3A;
  944.     else
  945.       *mv = 0x0402;
  946.   else if (s[0] == 'o')
  947.     if (side == black)
  948.       *mv = 0x3C3E;
  949.     else
  950.       *mv = 0x0406;
  951.   else
  952.     {
  953.       c1 = s[0] - 'a';
  954.       r1 = s[1] - '1';
  955.       c2 = s[2] - 'a';
  956.       r2 = s[3] - '1';
  957.       *mv = (locn (r1, c1) << 8) | locn (r2, c2);
  958.     }
  959.   return (1);
  960. }
  961.  
  962. void
  963. GetOpenings (void)
  964.  
  965. /*
  966.    Read in the Opening Book file and parse the algebraic notation for a move
  967.    into an unsigned integer format indicating the from and to square. Create
  968.    a linked list of opening lines of play, with entry->next pointing to the
  969.    next line and entry->move pointing to a chunk of memory containing the
  970.    moves. More Opening lines of up to 256 half moves may be added to
  971.    gnuchess.book.
  972. */
  973. #ifndef BOOK
  974. #define BOOK "/usr/games/lib/gnuchess.book"
  975. #endif /* BOOK */
  976. {
  977.   FILE *fd;
  978.   int c, i, j, side;
  979.   /* char buffr[2048]; */
  980.   struct BookEntry *entry;
  981.   unsigned short mv, *mp, tmp[100];
  982.  
  983.   if ((fd = fopen (BOOK, "r")) == NULL)
  984.     fd = fopen ("gnuchess.book", "r");
  985.   if (fd != NULL)
  986.     {
  987.       /* setvbuf(fd,buffr,_IOFBF,2048); */
  988.       Book = NULL;
  989.       i = 0;
  990.       side = white;
  991.       while ((c = parse (fd, &mv, side)) >= 0)
  992.         if (c == 1)
  993.           {
  994.             tmp[++i] = mv;
  995.             side = otherside[side];
  996.           }
  997.         else if (c == 0 && i > 0)
  998.           {
  999.             entry = (struct BookEntry *) malloc (sizeof (struct BookEntry));
  1000.             mp = (unsigned short *) malloc ((i + 1) * sizeof (unsigned short));
  1001.             if (!entry || !mp)
  1002.               {
  1003.                 Book = NULL;
  1004.                 ShowMessage ("warning: can\'t load book, out of memory.");
  1005.                 return;
  1006.               }
  1007.             entry->mv = mp;
  1008.             entry->next = Book;
  1009.             Book = entry;
  1010.             for (j = 1; j <= i; j++)
  1011.               *(mp++) = tmp[j];
  1012.             *mp = 0;
  1013.             i = 0;
  1014.             side = white;
  1015.           }
  1016.       fclose (fd);
  1017.     }
  1018.   else
  1019.     ShowMessage ("warning: can\'t find book.");
  1020. }
  1021.  
  1022.  
  1023. void
  1024. OpeningBook (unsigned short *hint)
  1025.  
  1026. /*
  1027.   Go thru each of the opening lines of play and check for a match with the
  1028.   current game listing. If a match occurs, generate a random number. If this
  1029.   number is the largest generated so far then the next move in this line
  1030.   becomes the current "candidate". After all lines are checked, the
  1031.   candidate move is put at the top of the Tree[] array and will be played by
  1032.   the program. Note that the program does not handle book transpositions.
  1033. */
  1034.  
  1035. {
  1036.   short j, pnt;
  1037.   unsigned short m, *mp;
  1038.   unsigned r, r0;
  1039.   struct BookEntry *p;
  1040.  
  1041.   srand ((unsigned int) time ((long *) 0));
  1042.   r0 = m = 0;
  1043.   p = Book;
  1044.   while (p != NULL)
  1045.     {
  1046.       mp = p->mv;
  1047.       for (j = 1; j <= GameCnt; j++)
  1048.         if (GameList[j].gmove != *(mp++))
  1049.           break;
  1050.       if (j > GameCnt)
  1051.         if ((r = urand ()) > r0)
  1052.           {
  1053.             r0 = r;
  1054.             m = *mp;
  1055.             *hint = *(++mp);
  1056.           }
  1057.       p = p->next;
  1058.     }
  1059.  
  1060.   for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
  1061.     if (((Tree[pnt].f << 8) | Tree[pnt].t) == m)
  1062.       Tree[pnt].score = 0;
  1063.   pick (TrPnt[1], TrPnt[2] - 1);
  1064.   if (Tree[TrPnt[1]].score < 0)
  1065.     Book = NULL;
  1066. }
  1067.  
  1068.  
  1069. inline void
  1070. repetition (short int *cnt)
  1071.  
  1072. /*
  1073.   Check for draw by threefold repetition.
  1074. */
  1075.  
  1076. {
  1077.   register short i, c, f, t;
  1078.   short b[64];
  1079.   unsigned short m;
  1080.  
  1081.   *cnt = c = 0;
  1082.   if (GameCnt > Game50 + 3)
  1083.     {
  1084. #ifdef NOMEMSET
  1085.       for (i = 0; i < 64; b[i++] = 0) ;
  1086. #else
  1087.       memset ((char *) b, 0, sizeof (b));
  1088. #endif /* NOMEMSET */
  1089.       for (i = GameCnt; i > Game50; i--)
  1090.         {
  1091.           m = GameList[i].gmove;
  1092.           f = m >> 8;
  1093.           t = m & 0xFF;
  1094.           if (++b[f] == 0)
  1095.             c--;
  1096.           else
  1097.             c++;
  1098.           if (--b[t] == 0)
  1099.             c--;
  1100.           else
  1101.             c++;
  1102.           if (c == 0)
  1103.             (*cnt)++;
  1104.         }
  1105.     }
  1106. }
  1107.  
  1108. int
  1109. search (short int side,
  1110.         short int ply,
  1111.         short int depth,
  1112.         short int alpha,
  1113.         short int beta,
  1114.         unsigned short int *bstline,
  1115.         short int *rpt)
  1116.  
  1117. /*
  1118.   Perform an alpha-beta search to determine the score for the current board
  1119.   position. If depth <= 0 only capturing moves, pawn promotions and
  1120.   responses to check are generated and searched, otherwise all moves are
  1121.   processed. The search depth is modified for check evasions, certain
  1122.   re-captures and threats. Extensions may continue for up to 11 ply beyond
  1123.   the nominal search depth.
  1124. */
  1125.  
  1126. #define UpdateSearchStatus \
  1127. {\
  1128.    if (flag.post) ShowCurrentMove(pnt,node->f,node->t);\
  1129.      if (pnt > TrPnt[1])\
  1130.        {\
  1131.           d = best-Zscore; e = best-node->score;\
  1132.             if (best < alpha) ExtraTime = 10*ResponseTime;\
  1133.             else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
  1134.             else if (d > -zwndw) ExtraTime = 0;\
  1135.             else if (d > -3*zwndw) ExtraTime = ResponseTime;\
  1136.             else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
  1137.             else ExtraTime = 5*ResponseTime;\
  1138.             }\
  1139.             }
  1140. #define prune (cf && score+node->score < alpha)
  1141. #define ReCapture (flag.rcptr && score > alpha && score < beta &&\
  1142.                    ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
  1143. /* && depth == Sdepth-ply+1 */
  1144. #define Parry (hung[side] > 1 && ply == Sdepth+1)
  1145. #define MateThreat (ply < Sdepth+4 && ply > 4 &&\
  1146.                     ChkFlag[ply-2] && ChkFlag[ply-4] &&\
  1147.                     ChkFlag[ply-2] != ChkFlag[ply-4])
  1148.  
  1149. {
  1150.   register short j, pnt;
  1151.   short best, tempb, tempc, tempsf, tempst;
  1152.   short xside, pbst, d, e, cf, score, rcnt, slk, InChk;
  1153.   unsigned short mv, nxtline[maxdepth];
  1154.   struct leaf *node, tmp;
  1155.  
  1156.   NodeCnt++;
  1157.   xside = otherside[side];
  1158.  
  1159.   if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  1160.     repetition (rpt);
  1161.   else
  1162.     *rpt = 0;
  1163.   /* Detect repetitions a bit earlier. SMC. 12/89 */
  1164.   if (*rpt == 1 && ply > 1)
  1165.     return (0);
  1166.   /* if (*rpt >= 2) return(0); */
  1167.  
  1168.   score = evaluate (side, ply, alpha, beta, INCscore, &slk, &InChk);
  1169.   if (score > 9000)
  1170.     {
  1171.       bstline[ply] = 0;
  1172.       return (score);
  1173.     }
  1174.   if (depth > 0)
  1175.     {
  1176.       /* Allow opponent a chance to check again */
  1177.       if (InChk)
  1178.         depth = (depth < 2) ? 2 : depth;
  1179.       else if (PawnThreat[ply - 1] || ReCapture)
  1180.         ++depth;
  1181.     }
  1182.   else
  1183.     {
  1184.       if (score >= alpha &&
  1185.           (InChk || PawnThreat[ply - 1] || Parry))
  1186.         depth = 1;
  1187.       else if (score <= beta && MateThreat)
  1188.         depth = 1;
  1189.     }
  1190.  
  1191. #if ttblsz
  1192.   if (depth > 0 && flag.hash && ply > 1)
  1193.     {
  1194.       if (ProbeTTable (side, depth, &alpha, &beta, &score) == false)
  1195. #ifdef HASHFILE
  1196.         if (hashfile && (depth > 5) && (GameCnt < 12))
  1197.           ProbeFTable (side, depth, &alpha, &beta, &score);
  1198. #else
  1199.       /* do nothing */;
  1200. #endif /* HASHFILE */
  1201.       bstline[ply] = PV;
  1202.       bstline[ply + 1] = 0;
  1203.       if (beta == -20000)
  1204.         return (score);
  1205.       if (alpha > beta)
  1206.         return (alpha);
  1207.     }
  1208. #endif /* ttblsz */
  1209.   if (Sdepth == 1)
  1210.     d = 7;
  1211.   else
  1212.     d = 11;
  1213.   if (ply > Sdepth + d || (depth < 1 && score > beta))
  1214.     /* score >= beta ?? */
  1215.     return (score);
  1216.  
  1217.   if (ply > 1)
  1218.     if (depth > 0)
  1219.       MoveList (side, ply);
  1220.     else
  1221.       CaptureList (side, ply);
  1222.  
  1223.   if (TrPnt[ply] == TrPnt[ply + 1])
  1224.     return (score);
  1225.  
  1226.   cf = (depth < 1 && ply > Sdepth + 1 && !ChkFlag[ply - 2] && !slk);
  1227.  
  1228.   if (depth > 0)
  1229.     best = -12000;
  1230.   else
  1231.     best = score;
  1232.   if (best > alpha)
  1233.     alpha = best;
  1234.  
  1235.   for (pnt = pbst = TrPnt[ply];
  1236.        pnt < TrPnt[ply + 1] && best <= beta;    /* best < beta ?? */
  1237.        pnt++)
  1238.     {
  1239.       if (ply > 1)
  1240.         pick (pnt, TrPnt[ply + 1] - 1);
  1241.       node = &Tree[pnt];
  1242.       mv = (node->f << 8) | node->t;
  1243.       nxtline[ply + 1] = 0;
  1244.  
  1245.       if (prune)
  1246.         break;
  1247.       if (ply == 1)
  1248.         UpdateSearchStatus;
  1249.  
  1250.       if (!(node->flags & exact))
  1251.         {
  1252.           MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  1253.           CptrFlag[ply] = (node->flags & capture);
  1254.           PawnThreat[ply] = (node->flags & pwnthrt);
  1255.           Tscore[ply] = node->score;
  1256.           PV = node->reply;
  1257.           node->score = -search (xside, ply + 1,
  1258.                                  (depth > 0) ? depth - 1 : 0,
  1259.                                  -beta, -alpha,
  1260.                                  nxtline, &rcnt);
  1261.           if (abs (node->score) > 9000)
  1262.             node->flags |= exact;
  1263.           else if (rcnt == 1)
  1264.             node->score /= 2;
  1265.           if (rcnt >= 2 || GameCnt - Game50 > 99 ||
  1266.               (node->score == 9999 - ply && !ChkFlag[ply]))
  1267.             {
  1268.               node->flags |= draw;
  1269.               node->flags |= exact;
  1270.               if (side == computer)
  1271.                 node->score = contempt;
  1272.               else
  1273.                 node->score = -contempt;
  1274.             }
  1275.           node->reply = nxtline[ply + 1];
  1276.           UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1277.         }
  1278.       if (node->score > best && !flag.timeout)
  1279.         {
  1280.           if (depth > 0)
  1281.             if (node->score > alpha && !(node->flags & exact))
  1282.               node->score += depth;
  1283.           best = node->score;
  1284.           pbst = pnt;
  1285.           if (best > alpha)
  1286.             alpha = best;
  1287.           for (j = ply + 1; nxtline[j] > 0; j++)
  1288.             bstline[j] = nxtline[j];
  1289.           bstline[j] = 0;
  1290.           bstline[ply] = mv;
  1291.           if (ply == 1)
  1292.             {
  1293.               if (best > root->score)
  1294.                 {
  1295.                   tmp = Tree[pnt];
  1296.                   for (j = pnt - 1; j >= 0; j--)
  1297.                     Tree[j + 1] = Tree[j];
  1298.                   Tree[0] = tmp;
  1299.                   pbst = 0;
  1300.                 }
  1301.               if (Sdepth > 2)
  1302.                 if (best > beta)
  1303.                   ShowResults (best, bstline, '+');
  1304.                 else if (best < alpha)
  1305.                   ShowResults (best, bstline, '-');
  1306.                 else
  1307.                   ShowResults (best, bstline, '&');
  1308.             }
  1309.         }
  1310.       if (NodeCnt > ETnodes)
  1311.         ElapsedTime (0);
  1312.       if (flag.timeout)
  1313.         return (-Tscore[ply - 1]);
  1314.     }
  1315.  
  1316.   node = &Tree[pbst];
  1317.   mv = (node->f << 8) | node->t;
  1318. #if ttblsz
  1319.   if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  1320.     {
  1321.       PutInTTable (side, best, depth, alpha, beta, mv);
  1322. #ifdef HASHFILE
  1323.       if (hashfile && (depth > 5) && (GameCnt < 12))
  1324.         PutInFTable (side, best, depth, alpha, beta, node->f, node->t);
  1325. #endif /* HASHFILE */
  1326.     }
  1327. #endif /* ttblsz */
  1328.   if (depth > 0)
  1329.     {
  1330.       j = (node->f << 6) | node->t;
  1331.       if (side == black)
  1332.         j |= 0x1000;
  1333.       if (history[j] < 150)
  1334.         history[j] += (unsigned char) 2 * depth;
  1335.       if (node->t != (GameList[GameCnt].gmove & 0xFF))
  1336.         if (best <= beta)
  1337.           killr3[ply] = mv;
  1338.         else if (mv != killr1[ply])
  1339.           {
  1340.             killr2[ply] = killr1[ply];
  1341.             killr1[ply] = mv;
  1342.           }
  1343.       if (best > 9000)
  1344.         killr0[ply] = mv;
  1345.       else
  1346.         killr0[ply] = 0;
  1347.     }
  1348.   return (best);
  1349. }
  1350.  
  1351. #if ttblsz
  1352. /*
  1353.   hashbd contains a 32 bit "signature" of the board position. hashkey
  1354.   contains a 16 bit code used to address the hash table. When a move is
  1355.   made, XOR'ing the hashcode of moved piece on the from and to squares with
  1356.   the hashbd and hashkey values keeps things current.
  1357. */
  1358. #define UpdateHashbd(side, piece, f, t) \
  1359. {\
  1360.   if ((f) >= 0)\
  1361.     {\
  1362.       hashbd ^= hashcode[side][piece][f].bd;\
  1363.       hashkey ^= hashcode[side][piece][f].key;\
  1364.     }\
  1365.   if ((t) >= 0)\
  1366.     {\
  1367.       hashbd ^= hashcode[side][piece][t].bd;\
  1368.       hashkey ^= hashcode[side][piece][t].key;\
  1369.     }\
  1370. }
  1371.  
  1372. #define CB(i) (unsigned char) ((color[2 * (i)] ? 0x80 : 0)\
  1373.                | (board[2 * (i)] << 4)\
  1374.                | (color[2 * (i) + 1] ? 0x8 : 0)\
  1375.                | (board[2 * (i) + 1]))
  1376.  
  1377. int
  1378. ProbeTTable (short int side,
  1379.              short int depth,
  1380.              short int *alpha,
  1381.              short int *beta,
  1382.              short int *score)
  1383.  
  1384. /*
  1385.   Look for the current board position in the transposition table.
  1386. */
  1387.  
  1388. {
  1389.   register struct hashentry *ptbl;
  1390.   register unsigned short i;
  1391.  
  1392. #ifdef __ZTC__
  1393.   ptbl = &zttable(side,hashkey & (ttblsz - 1));
  1394. #else
  1395.   ptbl = &ttable[side][hashkey & (ttblsz - 1)];
  1396. #endif /* __ZTC__ */
  1397.   /* rehash max rehash times */
  1398.   for (i = 1; ptbl->hashbd != hashbd && i <= rehash; i++)
  1399. #ifdef __ZTC__
  1400.     ptbl = &zttable(side,(hashkey + i) & (ttblsz - 1));
  1401. #else
  1402.     ptbl = &ttable[side][(hashkey + i) & (ttblsz - 1)];
  1403. #endif /* __ZTC__ */
  1404.   if ((short) ptbl->depth >= depth && ptbl->hashbd == hashbd)
  1405.     {
  1406.       HashCnt++;
  1407. #ifdef HASHTEST
  1408.       for (i = 0; i < 32; i++)
  1409.         {
  1410.           if (ptbl->bd[i] != CB(i))
  1411.             {
  1412.               HashCol++;
  1413.               ShowMessage("ttable collision detected");
  1414.               break;
  1415.             }
  1416.         }
  1417. #endif /* HASHTEST */
  1418.  
  1419.       PV = ptbl->mv;
  1420.       if (ptbl->flags & truescore)
  1421.         {
  1422.           *score = ptbl->score;
  1423.           *beta = -20000;
  1424.         }
  1425. #if 0 /* commented out, why? */
  1426.       else if (ptbl->flags & upperbound)
  1427.         {
  1428.           if (ptbl->score < *beta) *beta = ptbl->score+1;
  1429.         }
  1430. #endif
  1431.       else if (ptbl->flags & lowerbound)
  1432.         {
  1433.           if (ptbl->score > *alpha)
  1434.             *alpha = ptbl->score - 1;
  1435.         }
  1436.       return(true);
  1437.     }
  1438.   return(false);
  1439. }
  1440.  
  1441. void
  1442. PutInTTable (short int side,
  1443.              short int score,
  1444.              short int depth,
  1445.              short int alpha,
  1446.              short int beta,
  1447.              unsigned short int mv)
  1448.  
  1449. /*
  1450.   Store the current board position in the transposition table.
  1451. */
  1452.  
  1453. {
  1454.   register struct hashentry *ptbl;
  1455.   register unsigned short i;
  1456.  
  1457. #ifdef __ZTC__
  1458.   ptbl = &zttable(side,hashkey & (ttblsz - 1));
  1459. #else
  1460.   ptbl = &ttable[side][hashkey & (ttblsz - 1)];
  1461. #endif /* __ZTC__ */
  1462.  
  1463.   /* rehash max rehash times */
  1464.   for (i = 1; depth < ptbl->depth && ptbl->hashbd != hashbd && i <= rehash; i++)
  1465. #ifdef __ZTC__
  1466.     ptbl = &zttable(side,(hashkey + i) & (ttblsz - 1));
  1467. #else
  1468.     ptbl = &ttable[side][(hashkey + i) & (ttblsz - 1)];
  1469. #endif /* __ZTC__ */
  1470.   if (depth >= ptbl->depth || ptbl->hashbd != hashbd)
  1471.     {
  1472.       ptbl->hashbd = hashbd;
  1473.       ptbl->depth = (unsigned char) depth;
  1474.       ptbl->score = score;
  1475.       ptbl->mv = mv;
  1476.       ptbl->flags = 0;
  1477.       if (score < alpha)
  1478.         ptbl->flags |= upperbound;
  1479.       else if (score > beta)
  1480.         ptbl->flags |= lowerbound;
  1481.       else
  1482.         ptbl->flags |= truescore;
  1483. #ifdef HASHTEST
  1484.       for (i = 0; i < 32; i++)
  1485.         {
  1486.           ptbl->bd[i] = CB(i);
  1487.         }
  1488. #endif /* HASHTEST */
  1489.     }
  1490. }
  1491.  
  1492. void
  1493. ZeroTTable (void)
  1494. {
  1495.   register int side, i;
  1496.  
  1497.   if (flag.hash)
  1498.     for (side = white; side <= black; side++)
  1499.       for (i = 0; i < ttblsz; i++)
  1500. #ifdef __ZTC__
  1501.         zttable(side,i).depth = 0;
  1502. #else
  1503.         ttable[side][i].depth = 0;
  1504. #endif /* __ZTC__ */
  1505. }
  1506.  
  1507. #ifdef HASHFILE
  1508. int
  1509. ProbeFTable(short int side,
  1510.             short int depth,
  1511.             short int *alpha,
  1512.             short int *beta,
  1513.             short int *score)
  1514.  
  1515. /*
  1516.   Look for the current board position in the persistent transposition table.
  1517. */
  1518.  
  1519. {
  1520.   register unsigned short i, j;
  1521.   register unsigned long hashix;
  1522.   short s;
  1523.   struct fileentry new, t;
  1524.  
  1525.   if (side == white)
  1526.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  1527.   else
  1528.     hashix = hashkey | 1 & (filesz - 1);
  1529.  
  1530.   for (i = 0; i < 32; i++)
  1531.     new.bd[i] = CB(i);
  1532.   new.flags = 0;
  1533.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  1534.     new.flags |= queencastle;
  1535.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  1536.     new.flags |= kingcastle;
  1537.  
  1538.   for (i = 0; i < frehash; i++)
  1539.     {
  1540.       fseek(hashfile,
  1541.             sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  1542.             SEEK_SET);
  1543.       fread(&t, sizeof(struct fileentry), 1, hashfile);
  1544.       for (j = 0; j < 32; j++)
  1545.         if (t.bd[j] != new.bd[j])
  1546.           break;
  1547.       if (((short) t.depth >= depth) && (j >= 32)
  1548.           && (new.flags == (t.flags & (kingcastle | queencastle))))
  1549.         {
  1550.           FHashCnt++;
  1551.           PV = (t.f << 8) | t.t;
  1552.           s = (t.sh << 8) | t.sl;
  1553.           if (t.flags & truescore)
  1554.             {
  1555.               *score = s;
  1556.               *beta = -20000;
  1557.             }
  1558.           else if (t.flags & lowerbound)
  1559.             {
  1560.               if (s > *alpha)
  1561.                 *alpha = s - 1;
  1562.             }
  1563.           return(true);
  1564.         }
  1565.     }
  1566.   return(false);
  1567. }
  1568.  
  1569. void
  1570. PutInFTable (short int side,
  1571.              short int score,
  1572.              short int depth,
  1573.              short int alpha,
  1574.              short int beta,
  1575.              short unsigned int f,
  1576.              short unsigned int t)
  1577.  
  1578. /*
  1579.   Store the current board position in the persistent transposition table.
  1580. */
  1581.  
  1582. {
  1583.   register unsigned short i;
  1584.   register unsigned long hashix;
  1585.   struct fileentry new, tmp;
  1586.  
  1587.   if (side == white)
  1588.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  1589.   else
  1590.     hashix = hashkey | 1 & (filesz - 1);
  1591.  
  1592.   for (i = 0; i < 32; i++)
  1593.     new.bd[i] = CB(i);
  1594.   new.f = (unsigned char) f;
  1595.   new.t = (unsigned char) t;
  1596.   new.flags = 0;
  1597.   if (score < alpha)
  1598.     new.flags |= upperbound;
  1599.   else if (score > beta)
  1600.     new.flags |= lowerbound;
  1601.   else
  1602.     new.flags |= truescore;
  1603.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  1604.     new.flags |= queencastle;
  1605.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  1606.     new.flags |= kingcastle;
  1607.   new.depth = (unsigned char) depth;
  1608.   new.sh = (unsigned char) (score >> 8);
  1609.   new.sl = (unsigned char) (score & 0xFF);
  1610.  
  1611.   for (i = 0; i < frehash; i++)
  1612.     {
  1613.       fseek(hashfile,
  1614.             sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  1615.             SEEK_SET);
  1616.       fread(&tmp, sizeof(struct fileentry), 1, hashfile);
  1617.       if ((short) tmp.depth <= depth)
  1618.         {
  1619.           fseek(hashfile,
  1620.                 sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  1621.                 SEEK_SET);
  1622.           fwrite (&new, sizeof(struct fileentry), 1, hashfile);
  1623.           break;
  1624.         }
  1625.     }
  1626. }
  1627. #endif /* HASHFILE */
  1628. #endif /* ttblsz */
  1629.  
  1630. void
  1631. ZeroRPT (void)
  1632. {
  1633.   register int side, i;
  1634.  
  1635.   for (side = white; side <= black; side++)
  1636.     for (i = 0; i < 256; i++)
  1637.       rpthash[side][i] = 0;
  1638. }
  1639.  
  1640. #define Link(from,to,flag,s) \
  1641. {\
  1642.    node->f = from; node->t = to;\
  1643.      node->reply = 0;\
  1644.        node->flags = flag;\
  1645.          node->score = s;\
  1646.            ++node;\
  1647.              ++TrPnt[ply+1];\
  1648.              }
  1649.  
  1650. static inline void
  1651. LinkMove (short int ply,
  1652.           short int f,
  1653.           short int t,
  1654.           short int flag,
  1655.           short int xside)
  1656.  
  1657. /*
  1658.   Add a move to the tree.  Assign a bonus to order the moves
  1659.   as follows:
  1660.   1. Principle variation
  1661.   2. Capture of last moved piece
  1662.   3. Other captures (major pieces first)
  1663.   4. Killer moves
  1664.   5. "history" killers
  1665. */
  1666.  
  1667. {
  1668.   register short s, z;
  1669.   register unsigned short mv;
  1670.   register struct leaf *node;
  1671.  
  1672.   node = &Tree[TrPnt[ply + 1]];
  1673.   mv = (f << 8) | t;
  1674.   s = 0;
  1675.   if (mv == Swag0)
  1676.     s = 2000;
  1677.   else if (mv == Swag1)
  1678.     s = 60;
  1679.   else if (mv == Swag2)
  1680.     s = 50;
  1681.   else if (mv == Swag3)
  1682.     s = 40;
  1683.   else if (mv == Swag4)
  1684.     s = 30;
  1685.   z = (f << 6) | t;
  1686.   if (xside == white)
  1687.     z |= 0x1000;
  1688.   s += history[z];
  1689.   if (color[t] != neutral)
  1690.     {
  1691.       if (t == TOsquare)
  1692.         s += 500;
  1693.       s += value[board[t]] - board[f];
  1694.     }
  1695.   if (board[f] == pawn)
  1696.     if (row (t) == 0 || row (t) == 7)
  1697.       {
  1698.         flag |= promote;
  1699.         s += 800;
  1700.         Link (f, t, flag | queen, s - 20000);
  1701.         s -= 200;
  1702.         Link (f, t, flag | knight, s - 20000);
  1703.         s -= 50;
  1704.         Link (f, t, flag | rook, s - 20000);
  1705.         flag |= bishop;
  1706.         s -= 50;
  1707.       }
  1708.     else if (row (t) == 1 || row (t) == 6)
  1709.       {
  1710.         flag |= pwnthrt;
  1711.         s += 600;
  1712.       }
  1713.   Link (f, t, flag, s - 20000);
  1714. }
  1715.  
  1716.  
  1717. static inline void
  1718. GenMoves (short int ply, short int sq, short int side, short int xside)
  1719.  
  1720. /*
  1721.   Generate moves for a piece. The moves are taken from the precalulated
  1722.   array nextpos/nextdir. If the board is free, next move is choosen from
  1723.   nextpos else from nextdir.
  1724. */
  1725.  
  1726. {
  1727.   register short u, piece;
  1728.   register unsigned char *ppos, *pdir;
  1729.  
  1730.   piece = board[sq];
  1731. #ifdef __ZTC__
  1732.   ppos = &znextpos(ptype[side][piece],sq,0);
  1733.   pdir = &znextdir(ptype[side][piece],sq,0);
  1734. #else
  1735.   ppos = nextpos[ptype[side][piece]][sq];
  1736.   pdir = nextdir[ptype[side][piece]][sq];
  1737. #endif /* __ZTC__ */
  1738.   if (piece == pawn)
  1739.     {
  1740.       u = ppos[sq];     /* follow no captures thread */
  1741.       if (color[u] == neutral)
  1742.         {
  1743.           LinkMove (ply, sq, u, 0, xside);
  1744.           u = ppos[u];
  1745.           if (color[u] == neutral)
  1746.             LinkMove (ply, sq, u, 0, xside);
  1747.         }
  1748.       u = pdir[sq];     /* follow captures thread */
  1749.       if (color[u] == xside)
  1750.         LinkMove (ply, sq, u, capture, xside);
  1751.       else
  1752.         if (u == epsquare)
  1753.           LinkMove (ply, sq, u, capture | epmask, xside);
  1754.       u = pdir[u];
  1755.       if (color[u] == xside)
  1756.         LinkMove (ply, sq, u, capture, xside);
  1757.       else
  1758.         if (u == epsquare)
  1759.           LinkMove (ply, sq, u, capture | epmask, xside);
  1760.     }
  1761.   else
  1762.     {
  1763.       u = ppos[sq];
  1764.       do
  1765.         {
  1766.           if (color[u] == neutral)
  1767.             {
  1768.               LinkMove (ply, sq, u, 0, xside);
  1769.               u = ppos[u];
  1770.             }
  1771.           else
  1772.             {
  1773.               if (color[u] == xside)
  1774.                 LinkMove (ply, sq, u, capture, xside);
  1775.               u = pdir[u];
  1776.             }
  1777.       } while (u != sq);
  1778.     }
  1779. }
  1780.  
  1781. void
  1782. MoveList (short int side, short int ply)
  1783.  
  1784. /*
  1785.   Fill the array Tree[] with all available moves for side to play. Array
  1786.   TrPnt[ply] contains the index into Tree[] of the first move at a ply.
  1787. */
  1788.  
  1789. {
  1790.   register short i, xside, f;
  1791.  
  1792.   xside = otherside[side];
  1793.   TrPnt[ply + 1] = TrPnt[ply];
  1794.   if (PV == 0)
  1795.     Swag0 = killr0[ply];
  1796.   else
  1797.     Swag0 = PV;
  1798.   Swag1 = killr1[ply];
  1799.   Swag2 = killr2[ply];
  1800.   Swag3 = killr3[ply];
  1801.   if (ply > 2)
  1802.     Swag4 = killr1[ply - 2];
  1803.   else
  1804.     Swag4 = 0;
  1805.   for (i = PieceCnt[side]; i >= 0; i--)
  1806.     GenMoves (ply, PieceList[side][i], side, xside);
  1807.   if (!castld[side])
  1808.     {
  1809.       f = PieceList[side][0];
  1810.       if (castle (side, f, f + 2, 0))
  1811.         {
  1812.           LinkMove (ply, f, f + 2, cstlmask, xside);
  1813.         }
  1814.       if (castle (side, f, f - 2, 0))
  1815.         {
  1816.           LinkMove (ply, f, f - 2, cstlmask, xside);
  1817.         }
  1818.     }
  1819. }
  1820.  
  1821. void
  1822. CaptureList (short int side, short int ply)
  1823.  
  1824. /*
  1825.   Fill the array Tree[] with all available cature and promote moves for
  1826.   side to play. Array TrPnt[ply] contains the index into Tree[]
  1827.   of the first move at a ply.
  1828. */
  1829.  
  1830. {
  1831.   register short u, sq, xside;
  1832.   register struct leaf *node;
  1833.   register unsigned char *ppos, *pdir;
  1834.   short i, piece, *PL, r7;
  1835.  
  1836.   xside = otherside[side];
  1837.   TrPnt[ply + 1] = TrPnt[ply];
  1838.   node = &Tree[TrPnt[ply]];
  1839.   r7 = rank7[side];
  1840.   PL = PieceList[side];
  1841.   for (i = 0; i <= PieceCnt[side]; i++)
  1842.     {
  1843.       sq = PL[i];
  1844.       piece = board[sq];
  1845.       if (sweep[piece])
  1846.         {
  1847. #ifdef __ZTC__
  1848.           ppos = &znextpos(piece,sq,0);
  1849.           pdir = &znextdir(piece,sq,0);
  1850. #else
  1851.           ppos = nextpos[piece][sq];
  1852.           pdir = nextdir[piece][sq];
  1853. #endif /* __ZTC__ */
  1854.           u = ppos[sq];
  1855.           do
  1856.             {
  1857.               if (color[u] == neutral)
  1858.                 u = ppos[u];
  1859.               else
  1860.                 {
  1861.                   if (color[u] == xside)
  1862.                     Link (sq, u, capture,
  1863.                           value[board[u]] + svalue[board[u]] - piece);
  1864.                   u = pdir[u];
  1865.                 }
  1866.           } while (u != sq);
  1867.         }
  1868.       else
  1869.         {
  1870. #ifdef __ZTC__
  1871.           pdir = &znextdir(ptype[side][piece],sq,0);
  1872. #else
  1873.           pdir = nextdir[ptype[side][piece]][sq];
  1874. #endif /* __ZTC__ */
  1875.           if (piece == pawn && row (sq) == r7)
  1876.             {
  1877.               u = pdir[sq];
  1878.               if (color[u] == xside)
  1879.                 Link (sq, u, capture | promote | queen, valueQ);
  1880.               u = pdir[u];
  1881.               if (color[u] == xside)
  1882.                 Link (sq, u, capture | promote | queen, valueQ);
  1883. #ifdef __ZTC__
  1884.               ppos = &znextpos(ptype[side][piece],sq,0);
  1885. #else
  1886.               ppos = nextpos[ptype[side][piece]][sq];
  1887. #endif /* __ZTC__ */
  1888.               u = ppos[sq]; /* also generate non capture promote */
  1889.               if (color[u] == neutral)
  1890.                 Link (sq, u, promote | queen, valueQ);
  1891.             }
  1892.           else
  1893.             {
  1894.               u = pdir[sq];
  1895.               do
  1896.                 {
  1897.                   if (color[u] == xside)
  1898.                     Link (sq, u, capture,
  1899.                           value[board[u]] + svalue[board[u]] - piece);
  1900.                   u = pdir[u];
  1901.               } while (u != sq);
  1902.             }
  1903.         }
  1904.     }
  1905. }
  1906.  
  1907.  
  1908. int
  1909. castle (short int side, short int kf, short int kt, short int iop)
  1910.  
  1911. /* Make or Unmake a castling move. */
  1912.  
  1913. {
  1914.   register short rf, rt, t0, xside;
  1915.  
  1916.   xside = otherside[side];
  1917.   if (kt > kf)
  1918.     {
  1919.       rf = kf + 3;
  1920.       rt = kt - 1;
  1921.     }
  1922.   else
  1923.     {
  1924.       rf = kf - 4;
  1925.       rt = kt + 1;
  1926.     }
  1927.   if (iop == 0)
  1928.     {
  1929.       if (kf != kingP[side] ||
  1930.           board[kf] != king ||
  1931.           board[rf] != rook ||
  1932.           Mvboard[kf] != 0 ||
  1933.           Mvboard[rf] != 0 ||
  1934.           color[kt] != neutral ||
  1935.           color[rt] != neutral ||
  1936.           color[kt - 1] != neutral ||
  1937.           SqAtakd (kf, xside) ||
  1938.           SqAtakd (kt, xside) ||
  1939.           SqAtakd (rt, xside))
  1940.         return (false);
  1941.     }
  1942.   else
  1943.     {
  1944.       if (iop == 1)
  1945.         {
  1946.           castld[side] = true;
  1947.           Mvboard[kf]++;
  1948.           Mvboard[rf]++;
  1949.         }
  1950.       else
  1951.         {
  1952.           castld[side] = false;
  1953.           Mvboard[kf]--;
  1954.           Mvboard[rf]--;
  1955.           t0 = kt;
  1956.           kt = kf;
  1957.           kf = t0;
  1958.           t0 = rt;
  1959.           rt = rf;
  1960.           rf = t0;
  1961.         }
  1962.       board[kt] = king;
  1963.       color[kt] = side;
  1964.       Pindex[kt] = 0;
  1965.       board[kf] = no_piece;
  1966.       color[kf] = neutral;
  1967.       board[rt] = rook;
  1968.       color[rt] = side;
  1969.       Pindex[rt] = Pindex[rf];
  1970.       board[rf] = no_piece;
  1971.       color[rf] = neutral;
  1972.       PieceList[side][Pindex[kt]] = kt;
  1973.       PieceList[side][Pindex[rt]] = rt;
  1974. #if ttblsz
  1975.       UpdateHashbd (side, king, kf, kt);
  1976.       UpdateHashbd (side, rook, rf, rt);
  1977. #endif /* ttblsz */
  1978.     }
  1979.   return (true);
  1980. }
  1981.  
  1982.  
  1983. static inline void
  1984. EnPassant (short int xside, short int f, short int t, short int iop)
  1985.  
  1986. /*
  1987.   Make or unmake an en passant move.
  1988. */
  1989.  
  1990. {
  1991.   register short l;
  1992.  
  1993.   if (t > f)
  1994.     l = t - 8;
  1995.   else
  1996.     l = t + 8;
  1997.   if (iop == 1)
  1998.     {
  1999.       board[l] = no_piece;
  2000.       color[l] = neutral;
  2001.     }
  2002.   else
  2003.     {
  2004.       board[l] = pawn;
  2005.       color[l] = xside;
  2006.     }
  2007.   InitializeStats ();
  2008. }
  2009.  
  2010.  
  2011. static inline void
  2012. UpdatePieceList (short int side, short int sq, short int iop)
  2013.  
  2014. /*
  2015.   Update the PieceList and Pindex arrays when a piece is captured or when a
  2016.   capture is unmade.
  2017. */
  2018.  
  2019. {
  2020.   register short i;
  2021.   if (iop == 1)
  2022.     {
  2023.       PieceCnt[side]--;
  2024.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  2025.         {
  2026.           PieceList[side][i] = PieceList[side][i + 1];
  2027.           Pindex[PieceList[side][i]] = i;
  2028.         }
  2029.     }
  2030.   else
  2031.     {
  2032.       PieceCnt[side]++;
  2033.       PieceList[side][PieceCnt[side]] = sq;
  2034.       Pindex[sq] = PieceCnt[side];
  2035.     }
  2036. }
  2037.  
  2038. void
  2039. MakeMove (short int side,
  2040.           struct leaf * node,
  2041.           short int *tempb,
  2042.           short int *tempc,
  2043.           short int *tempsf,
  2044.           short int *tempst,
  2045.           short int *INCscore)
  2046.  
  2047. /*
  2048.   Update Arrays board[], color[], and Pindex[] to reflect the new board
  2049.   position obtained after making the move pointed to by node. Also update
  2050.   miscellaneous stuff that changes when a move is made.
  2051. */
  2052.  
  2053. {
  2054.   register short f, t, xside, ct, cf;
  2055.  
  2056.   xside = otherside[side];
  2057.   GameCnt++;
  2058.   f = node->f;
  2059.   t = node->t;
  2060.   epsquare = -1;
  2061.   FROMsquare = f;
  2062.   TOsquare = t;
  2063.   *INCscore = 0;
  2064.   GameList[GameCnt].gmove = (f << 8) | t;
  2065.   if (node->flags & cstlmask)
  2066.     {
  2067.       GameList[GameCnt].piece = no_piece;
  2068.       GameList[GameCnt].color = side;
  2069.       (void) castle (side, f, t, 1);
  2070.     }
  2071.   else
  2072.     {
  2073.       if (!(node->flags & capture) && (board[f] != pawn))
  2074.         rpthash[side][hashkey & 0xFF]++;
  2075.       *tempc = color[t];
  2076.       *tempb = board[t];
  2077.       *tempsf = svalue[f];
  2078.       *tempst = svalue[t];
  2079.       GameList[GameCnt].piece = *tempb;
  2080.       GameList[GameCnt].color = *tempc;
  2081.       if (*tempc != neutral)
  2082.         {
  2083.           UpdatePieceList (*tempc, t, 1);
  2084.           if (*tempb == pawn)
  2085.             --PawnCnt[*tempc][column (t)];
  2086.           if (board[f] == pawn)
  2087.             {
  2088.               --PawnCnt[side][column (f)];
  2089.               ++PawnCnt[side][column (t)];
  2090.               cf = column (f);
  2091.               ct = column (t);
  2092.               if (PawnCnt[side][ct] > 1 + PawnCnt[side][cf])
  2093.                 *INCscore -= 15;
  2094.               else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  2095.                 *INCscore += 15;
  2096.               else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  2097.                 *INCscore -= 15;
  2098.             }
  2099.           mtl[xside] -= value[*tempb];
  2100.           if (*tempb == pawn)
  2101.             pmtl[xside] -= valueP;
  2102. #if ttblsz
  2103.           UpdateHashbd (xside, *tempb, -1, t);
  2104. #endif /* ttblsz */
  2105.           *INCscore += *tempst;
  2106.           Mvboard[t]++;
  2107.         }
  2108.       color[t] = color[f];
  2109.       board[t] = board[f];
  2110.       svalue[t] = svalue[f];
  2111.       Pindex[t] = Pindex[f];
  2112.       PieceList[side][Pindex[t]] = t;
  2113.       color[f] = neutral;
  2114.       board[f] = no_piece;
  2115.       if (board[t] == pawn)
  2116.         if (t - f == 16)
  2117.           epsquare = f + 8;
  2118.         else if (f - t == 16)
  2119.           epsquare = f - 8;
  2120.       if (node->flags & promote)
  2121.         {
  2122.           board[t] = node->flags & pmask;
  2123.           if (board[t] == queen)
  2124.             HasQueen[side]++;
  2125.           else if (board[t] == rook)
  2126.             HasRook[side]++;
  2127.           else if (board[t] == bishop)
  2128.             HasBishop[side]++;
  2129.           else if (board[t] == knight)
  2130.             HasKnight[side]++;
  2131.           --PawnCnt[side][column (t)];
  2132.           mtl[side] += value[board[t]] - valueP;
  2133.           pmtl[side] -= valueP;
  2134. #if ttblsz
  2135.           UpdateHashbd (side, pawn, f, -1);
  2136.           UpdateHashbd (side, board[t], f, -1);
  2137. #endif /* ttblsz */
  2138.           *INCscore -= *tempsf;
  2139.         }
  2140.       if (node->flags & epmask)
  2141.         EnPassant (xside, f, t, 1);
  2142.       else
  2143. #if ttblsz
  2144.         UpdateHashbd (side, board[t], f, t);
  2145. #else
  2146.         /* NOOP */;
  2147. #endif /* ttblsz */
  2148.       Mvboard[f]++;
  2149.     }
  2150. }
  2151.  
  2152. void
  2153. UnmakeMove (short int side,
  2154.             struct leaf * node,
  2155.             short int *tempb,
  2156.             short int *tempc,
  2157.             short int *tempsf,
  2158.             short int *tempst)
  2159.  
  2160. /*
  2161.   Take back a move.
  2162. */
  2163.  
  2164. {
  2165.   register short f, t, xside;
  2166.  
  2167.   xside = otherside[side];
  2168.   f = node->f;
  2169.   t = node->t;
  2170.   epsquare = -1;
  2171.   GameCnt--;
  2172.   if (node->flags & cstlmask)
  2173.     (void) castle (side, f, t, 2);
  2174.   else
  2175.     {
  2176.       color[f] = color[t];
  2177.       board[f] = board[t];
  2178.       svalue[f] = *tempsf;
  2179.       Pindex[f] = Pindex[t];
  2180.       PieceList[side][Pindex[f]] = f;
  2181.       color[t] = *tempc;
  2182.       board[t] = *tempb;
  2183.       svalue[t] = *tempst;
  2184.       if (node->flags & promote)
  2185.         {
  2186.           board[f] = pawn;
  2187.           ++PawnCnt[side][column (t)];
  2188.           mtl[side] += valueP - value[node->flags & pmask];
  2189.           pmtl[side] += valueP;
  2190. #if ttblsz
  2191.           UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  2192.           UpdateHashbd (side, pawn, -1, t);
  2193. #endif /* ttblsz */
  2194.         }
  2195.       if (*tempc != neutral)
  2196.         {
  2197.           UpdatePieceList (*tempc, t, 2);
  2198.           if (*tempb == pawn)
  2199.             ++PawnCnt[*tempc][column (t)];
  2200.           if (board[f] == pawn)
  2201.             {
  2202.               --PawnCnt[side][column (t)];
  2203.               ++PawnCnt[side][column (f)];
  2204.             }
  2205.           mtl[xside] += value[*tempb];
  2206.           if (*tempb == pawn)
  2207.             pmtl[xside] += valueP;
  2208. #if ttblsz
  2209.           UpdateHashbd (xside, *tempb, -1, t);
  2210. #endif /* ttblsz */
  2211.           Mvboard[t]--;
  2212.         }
  2213.       if (node->flags & epmask)
  2214.         EnPassant (xside, f, t, 2);
  2215.       else
  2216. #if ttblsz
  2217.         UpdateHashbd (side, board[f], f, t);
  2218. #else
  2219.       /* NOOP */;
  2220. #endif /* ttblsz */
  2221.       Mvboard[f]--;
  2222.       if (!(node->flags & capture) && (board[f] != pawn))
  2223.         rpthash[side][hashkey & 0xFF]--;
  2224.     }
  2225. }
  2226.  
  2227.  
  2228. void
  2229. InitializeStats (void)
  2230.  
  2231. /*
  2232.   Scan thru the board seeing what's on each square. If a piece is found,
  2233.   update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  2234.   determine the material for each side and set the hashkey and hashbd
  2235.   variables to represent the current board position. Array
  2236.   PieceList[side][indx] contains the location of all the pieces of either
  2237.   side. Array Pindex[sq] contains the indx into PieceList for a given
  2238.   square.
  2239. */
  2240.  
  2241. {
  2242.   register short i, sq;
  2243.   epsquare = -1;
  2244.   for (i = 0; i < 8; i++)
  2245.     PawnCnt[white][i] = PawnCnt[black][i] = 0;
  2246.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  2247.   PieceCnt[white] = PieceCnt[black] = 0;
  2248. #if ttblsz
  2249.   hashbd = hashkey = 0;
  2250. #endif /* ttblsz */
  2251.   for (sq = 0; sq < 64; sq++)
  2252.     if (color[sq] != neutral)
  2253.       {
  2254.         mtl[color[sq]] += value[board[sq]];
  2255.         if (board[sq] == pawn)
  2256.           {
  2257.             pmtl[color[sq]] += valueP;
  2258.             ++PawnCnt[color[sq]][column (sq)];
  2259.           }
  2260.         if (board[sq] == king)
  2261.           Pindex[sq] = 0;
  2262.         else
  2263.           Pindex[sq] = ++PieceCnt[color[sq]];
  2264.         PieceList[color[sq]][Pindex[sq]] = sq;
  2265. #if ttblsz
  2266.         hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  2267.         hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  2268. #endif /* ttblsz */
  2269.       }
  2270. }
  2271.  
  2272.  
  2273. int
  2274. SqAtakd (short int sq, short int side)
  2275.  
  2276. /*
  2277.   See if any piece with color 'side' ataks sq.  First check pawns then Queen,
  2278.   Bishop, Rook and King and last Knight.
  2279. */
  2280.  
  2281. {
  2282.   register short u;
  2283.   register unsigned char *ppos, *pdir;
  2284.   short xside;
  2285.  
  2286.   xside = otherside[side];
  2287. #ifdef __ZTC__
  2288.   pdir = &znextdir(ptype[xside][pawn],sq,0);
  2289. #else
  2290.   pdir = nextdir[ptype[xside][pawn]][sq];
  2291. #endif /* __ZTC__ */
  2292.   u = pdir[sq];         /* follow captures thread */
  2293.   if (u != sq)
  2294.     {
  2295.       if (board[u] == pawn && color[u] == side)
  2296.         return (true);
  2297.       u = pdir[u];
  2298.       if (u != sq && board[u] == pawn && color[u] == side)
  2299.         return (true);
  2300.     }
  2301.   /* king capture */
  2302.   if (distance (sq, PieceList[side][0]) == 1)
  2303.     return (true);
  2304.   /* try a queen bishop capture */
  2305. #ifdef __ZTC__
  2306.   ppos = &znextpos(bishop,sq,0);
  2307.   pdir = &znextdir(bishop,sq,0);
  2308. #else
  2309.   ppos = nextpos[bishop][sq];
  2310.   pdir = nextdir[bishop][sq];
  2311. #endif /* __ZTC__ */
  2312.   u = ppos[sq];
  2313.   do
  2314.     {
  2315.       if (color[u] == neutral)
  2316.         u = ppos[u];
  2317.       else
  2318.         {
  2319.           if (color[u] == side &&
  2320.               (board[u] == queen || board[u] == bishop))
  2321.             return (true);
  2322.           u = pdir[u];
  2323.         }
  2324.   } while (u != sq);
  2325.   /* try a queen rook capture */
  2326. #ifdef __ZTC__
  2327.   ppos = &znextpos(rook,sq,0);
  2328.   pdir = &znextdir(rook,sq,0);
  2329. #else
  2330.   ppos = nextpos[rook][sq];
  2331.   pdir = nextdir[rook][sq];
  2332. #endif /* __ZTC__ */
  2333.   u = ppos[sq];
  2334.   do
  2335.     {
  2336.       if (color[u] == neutral)
  2337.         u = ppos[u];
  2338.       else
  2339.         {
  2340.           if (color[u] == side &&
  2341.               (board[u] == queen || board[u] == rook))
  2342.             return (true);
  2343.           u = pdir[u];
  2344.         }
  2345.   } while (u != sq);
  2346.   /* try a knight capture */
  2347. #ifdef __ZTC__
  2348.   pdir = &znextdir(knight,sq,0);
  2349. #else
  2350.   pdir = nextdir[knight][sq];
  2351. #endif /* __ZTC__ */
  2352.   u = pdir[sq];
  2353.   do
  2354.     {
  2355.       if (color[u] == side && board[u] == knight)
  2356.         return (true);
  2357.       u = pdir[u];
  2358.   } while (u != sq);
  2359.   return (false);
  2360. }
  2361.  
  2362. static inline void
  2363. ataks (short int side, short int *a)
  2364.  
  2365. /*
  2366.   Fill array atak[][] with info about ataks to a square.  Bits 8-15 are set
  2367.   if the piece (king..pawn) ataks the square.  Bits 0-7 contain a count of
  2368.   total ataks to the square.
  2369. */
  2370.  
  2371. {
  2372.   register short u, c, sq;
  2373.   register unsigned char *ppos, *pdir;
  2374.   short i, piece, *PL;
  2375.  
  2376. #ifdef NOMEMSET
  2377.   for (u = 64; u; a[--u] = 0) ;
  2378. #else
  2379.   memset ((char *) a, 0, 64 * sizeof (a[0]));
  2380. #endif /* NOMEMSET */
  2381.   PL = PieceList[side];
  2382.   for (i = PieceCnt[side]; i >= 0; i--)
  2383.     {
  2384.       sq = PL[i];
  2385.       piece = board[sq];
  2386.       c = control[piece];
  2387.       if (sweep[piece])
  2388.         {
  2389. #ifdef __ZTC__
  2390.           ppos = &znextpos(piece,sq,0);
  2391.           pdir = &znextdir(piece,sq,0);
  2392. #else
  2393.           ppos = nextpos[piece][sq];
  2394.           pdir = nextdir[piece][sq];
  2395. #endif /* __ZTC__ */
  2396.           u = ppos[sq];
  2397.           do
  2398.             {
  2399.               a[u] = ++a[u] | c;
  2400.               u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2401.           } while (u != sq);
  2402.         }
  2403.       else
  2404.         {
  2405. #ifdef __ZTC__
  2406.           pdir = &znextdir(ptype[side][piece],sq,0);
  2407. #else
  2408.           pdir = nextdir[ptype[side][piece]][sq];
  2409. #endif /* __ZTC__ */
  2410.           u = pdir[sq]; /* follow captures thread for pawns */
  2411.           do
  2412.             {
  2413.               a[u] = ++a[u] | c;
  2414.               u = pdir[u];
  2415.           } while (u != sq);
  2416.         }
  2417.     }
  2418. }
  2419.  
  2420.  
  2421. /* ............    POSITIONAL EVALUATION ROUTINES    ............ */
  2422.  
  2423. int
  2424. evaluate (short int side,
  2425.           short int ply,
  2426.           short int alpha,
  2427.           short int beta,
  2428.           short int INCscore,
  2429.           short int *slk,
  2430.           short int *InChk)
  2431.  
  2432. /*
  2433.   Compute an estimate of the score by adding the positional score from the
  2434.   previous ply to the material difference. If this score falls inside a
  2435.   window which is 180 points wider than the alpha-beta window (or within a
  2436.   50 point window during quiescence search) call ScorePosition() to
  2437.   determine a score, otherwise return the estimated score. If one side has
  2438.   only a king and the other either has no pawns or no pieces then the
  2439.   function ScoreLoneKing() is called.
  2440. */
  2441.  
  2442. {
  2443.   register short evflag, xside;
  2444.   short s;
  2445.  
  2446.   xside = otherside[side];
  2447.   s = -Pscore[ply - 1] + mtl[side] - mtl[xside] - INCscore;
  2448.   hung[white] = hung[black] = 0;
  2449.   *slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
  2450.          (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0)));
  2451.  
  2452.   if (*slk)
  2453.     evflag = false;
  2454.   else
  2455.     evflag =
  2456.       (ply == 1 || ply < Sdepth ||
  2457.        ((ply == Sdepth + 1 || ply == Sdepth + 2) &&
  2458.         (s > alpha - xwndw && s < beta + xwndw)) ||
  2459.        (ply > Sdepth + 2 && s >= alpha - 25 && s <= beta + 25));
  2460.  
  2461.   if (evflag)
  2462.     {
  2463.       EvalNodes++;
  2464.       ataks (side, atak[side]);
  2465.       if (Anyatak (side, PieceList[xside][0]))
  2466.         return (10001 - ply);
  2467.       ataks (xside, atak[xside]);
  2468.       *InChk = Anyatak (xside, PieceList[side][0]);
  2469.       ScorePosition (side, &s);
  2470.     }
  2471.   else
  2472.     {
  2473.       if (SqAtakd (PieceList[xside][0], side))
  2474.         return (10001 - ply);
  2475.       *InChk = SqAtakd (PieceList[side][0], xside);
  2476.       if (*slk)
  2477.         ScoreLoneKing (side, &s);
  2478.     }
  2479.  
  2480.   Pscore[ply] = s - mtl[side] + mtl[xside];
  2481.   if (*InChk)
  2482.     ChkFlag[ply - 1] = Pindex[TOsquare];
  2483.   else
  2484.     ChkFlag[ply - 1] = 0;
  2485.   return (s);
  2486. }
  2487.  
  2488.  
  2489. static inline int
  2490. ScoreKPK (short int side,
  2491.           short int winner,
  2492.           short int loser,
  2493.           short int king1,
  2494.           short int king2,
  2495.           short int sq)
  2496.  
  2497. /*
  2498.   Score King and Pawns versus King endings.
  2499. */
  2500.  
  2501. {
  2502.   register short s, r;
  2503.  
  2504.   if (PieceCnt[winner] == 1)
  2505.     s = 50;
  2506.   else
  2507.     s = 120;
  2508.   if (winner == white)
  2509.     {
  2510.       if (side == loser)
  2511.         r = row (sq) - 1;
  2512.       else
  2513.         r = row (sq);
  2514.       if (row (king2) >= r && distance (sq, king2) < 8 - r)
  2515.         s += 10 * row (sq);
  2516.       else
  2517.         s = 500 + 50 * row (sq);
  2518.       if (row (sq) < 6)
  2519.         sq += 16;
  2520.       else
  2521.         if (row(sq) == 6)
  2522.           sq += 8;
  2523.     }
  2524.   else
  2525.     {
  2526.       if (side == loser)
  2527.         r = row (sq) + 1;
  2528.       else
  2529.         r = row (sq);
  2530.       if (row (king2) <= r && distance (sq, king2) < r + 1)
  2531.         s += 10 * (7 - row (sq));
  2532.       else
  2533.         s = 500 + 50 * (7 - row (sq));
  2534.       if (row (sq) > 1)
  2535.         sq -= 16;
  2536.       else
  2537.         if (row(sq) == 1)
  2538.           sq -= 8;
  2539.     }
  2540.   s += 8 * (taxicab (king2, sq) - taxicab (king1, sq));
  2541.   return (s);
  2542. }
  2543.  
  2544.  
  2545. static inline int
  2546. ScoreKBNK (short int winner, short int king1, short int king2)
  2547.  
  2548.  
  2549. /*
  2550.   Score King+Bishop+Knight versus King endings.
  2551.   This doesn't work all that well but it's better than nothing.
  2552. */
  2553.  
  2554. {
  2555.   register short s, sq, KBNKsq = 0;
  2556.  
  2557.   for (sq = 0; sq < 64; sq++)
  2558.     if (board[sq] == bishop)
  2559.       if (row (sq) % 2 == column (sq) % 2)
  2560.         KBNKsq = 0;
  2561.       else
  2562.         KBNKsq = 7;
  2563.  
  2564.   s = emtl[winner] - 300;
  2565.   if (KBNKsq == 0)
  2566.     s += KBNK[king2];
  2567.   else
  2568.     s += KBNK[locn (row (king2), 7 - column (king2))];
  2569.   s -= taxicab (king1, king2);
  2570.   s -= distance (PieceList[winner][1], king2);
  2571.   s -= distance (PieceList[winner][2], king2);
  2572.   return (s);
  2573. }
  2574.  
  2575.  
  2576. void
  2577. ScoreLoneKing (short int side, short int *score)
  2578.  
  2579. /*
  2580.   Static evaluation when loser has only a king and winner has no pawns or no
  2581.   pieces.
  2582. */
  2583.  
  2584. {
  2585.   register short winner, loser, king1, king2, s, i;
  2586.  
  2587.   UpdateWeights ();
  2588.   if (mtl[white] > mtl[black])
  2589.     winner = white;
  2590.   else
  2591.     winner = black;
  2592.   loser = otherside[winner];
  2593.   king1 = PieceList[winner][0];
  2594.   king2 = PieceList[loser][0];
  2595.  
  2596.   s = 0;
  2597.  
  2598.   if (pmtl[winner] > 0)
  2599.     for (i = 1; i <= PieceCnt[winner]; i++)
  2600.       s += ScoreKPK (side, winner, loser, king1, king2, PieceList[winner][i]);
  2601.  
  2602.   else if (emtl[winner] == valueB + valueN)
  2603.     s = ScoreKBNK (winner, king1, king2);
  2604.  
  2605.   else if (emtl[winner] > valueB)
  2606.     s = 500 + emtl[winner] - DyingKing[king2] - 2 * distance (king1, king2);
  2607.  
  2608.   if (side == winner)
  2609.     *score = s;
  2610.   else
  2611.     *score = -s;
  2612. }
  2613.  
  2614.  
  2615. static inline void
  2616. BRscan (short int sq, short int *s, short int *mob)
  2617.  
  2618. /*
  2619.   Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
  2620.   hung[] array if a pin is found.
  2621. */
  2622. {
  2623.   register short u, piece, pin;
  2624.   register unsigned char *ppos, *pdir;
  2625.   short *Kf;
  2626.  
  2627.   Kf = Kfield[c1];
  2628.   *mob = 0;
  2629.   piece = board[sq];
  2630. #ifdef __ZTC__
  2631.   ppos = &znextpos(piece,sq,0);
  2632.   pdir = &znextdir(piece,sq,0);
  2633. #else
  2634.   ppos = nextpos[piece][sq];
  2635.   pdir = nextdir[piece][sq];
  2636. #endif /* __ZTC__ */
  2637.   u = ppos[sq];
  2638.   pin = -1;                     /* start new direction */
  2639.   do
  2640.     {
  2641.       *s += Kf[u];
  2642.       if (color[u] == neutral)
  2643.         {
  2644.           (*mob)++;
  2645.           if (ppos[u] == pdir[u])
  2646.             pin = -1;           /* oops new direction */
  2647.           u = ppos[u];
  2648.         }
  2649.       else if (pin < 0)
  2650.         {
  2651.           if (board[u] == pawn || board[u] == king)
  2652.             u = pdir[u];
  2653.           else
  2654.             {
  2655.               if (ppos[u] != pdir[u])
  2656.                 pin = u;        /* not on the edge and on to find a pin */
  2657.               u = ppos[u];
  2658.             }
  2659.         }
  2660.       else
  2661.         {
  2662.           if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
  2663.             {
  2664.               if (color[pin] == c2)
  2665.                 {
  2666.                   *s += PINVAL;
  2667.                   if (atk2[pin] == 0 ||
  2668.                       atk1[pin] > control[board[pin]] + 1)
  2669.                     ++hung[c2];
  2670.                 }
  2671.               else
  2672.                 *s += XRAY;
  2673.             }
  2674.           pin = -1;             /* new direction */
  2675.           u = pdir[u];
  2676.         }
  2677.   } while (u != sq);
  2678. }
  2679.  
  2680.  
  2681. static inline void
  2682. KingScan (short int sq, short int *s)
  2683.  
  2684. /*
  2685.   Assign penalties if king can be threatened by checks, if squares
  2686.   near the king are controlled by the enemy (especially the queen),
  2687.   or if there are no pawns near the king.
  2688.   The following must be true:
  2689.   board[sq] == king
  2690.   c1 == color[sq]
  2691.   c2 == otherside[c1]
  2692. */
  2693.  
  2694. #define ScoreThreat \
  2695. if (color[u] != c2)\
  2696.   if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\
  2697.   else *s -= 3
  2698.  
  2699. {
  2700.   register short u;
  2701.   register unsigned char *ppos, *pdir;
  2702.   register short cnt, ok;
  2703.  
  2704.   cnt = 0;
  2705.   if (HasBishop[c2] || HasQueen[c2])
  2706.     {
  2707. #ifdef __ZTC__
  2708.       ppos = &znextpos(bishop,sq,0);
  2709.       pdir = &znextdir(bishop,sq,0);
  2710. #else
  2711.       ppos = nextpos[bishop][sq];
  2712.       pdir = nextdir[bishop][sq];
  2713. #endif /* __ZTC__ */
  2714.       u = ppos[sq];
  2715.       do
  2716.         {
  2717.           if (atk2[u] & ctlBQ)
  2718.             ScoreThreat;
  2719.           u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2720.       } while (u != sq);
  2721.     }
  2722.   if (HasRook[c2] || HasQueen[c2])
  2723.     {
  2724. #ifdef __ZTC__
  2725.       ppos = &znextpos(rook,sq,0);
  2726.       pdir = &znextdir(rook,sq,0);
  2727. #else
  2728.       ppos = nextpos[rook][sq];
  2729.       pdir = nextdir[rook][sq];
  2730. #endif /* __ZTC__ */
  2731.       u = ppos[sq];
  2732.       do
  2733.         {
  2734.           if (atk2[u] & ctlRQ)
  2735.             ScoreThreat;
  2736.           u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2737.       } while (u != sq);
  2738.     }
  2739.   if (HasKnight[c2])
  2740.     {
  2741. #ifdef __ZTC__
  2742.       pdir = &znextdir(knight,sq,0);
  2743. #else
  2744.       pdir = nextdir[knight][sq];
  2745. #endif /* __ZTC__ */
  2746.       u = pdir[sq];
  2747.       do
  2748.         {
  2749.           if (atk2[u] & ctlNN)
  2750.             ScoreThreat;
  2751.           u = pdir[u];
  2752.       } while (u != sq);
  2753.     }
  2754.   *s += (KSFTY * KTHRT[cnt]) / 16;
  2755.  
  2756.   cnt = 0;
  2757.   ok = false;
  2758. #ifdef __ZTC__
  2759.   pdir = &znextpos(king,sq,0);
  2760. #else
  2761.   pdir = nextpos[king][sq];
  2762. #endif /* __ZTC__ */
  2763.   u = pdir[sq];
  2764.   do
  2765.     {
  2766.       if (board[u] == pawn)
  2767.         ok = true;
  2768.       if (atk2[u] > atk1[u])
  2769.         {
  2770.           ++cnt;
  2771.           if (atk2[u] & ctlQ)
  2772.             if (atk2[u] > ctlQ + 1 && atk1[u] < ctlQ)
  2773.               *s -= 4 * KSFTY;
  2774.         }
  2775.       u = pdir[u];
  2776.   } while (u != sq);
  2777.   if (!ok)
  2778.     *s -= KSFTY;
  2779.   if (cnt > 1)
  2780.     *s -= KSFTY;
  2781. }
  2782.  
  2783.  
  2784. static inline int
  2785. trapped (short int sq)
  2786.  
  2787. /*
  2788.   See if the attacked piece has unattacked squares to move to.
  2789.   The following must be true:
  2790.   c1 == color[sq]
  2791.   c2 == otherside[c1]
  2792. */
  2793.  
  2794. {
  2795.   register short u, piece;
  2796.   register unsigned char *ppos, *pdir;
  2797.  
  2798.   piece = board[sq];
  2799. #ifdef __ZTC__
  2800.   ppos = &znextpos(ptype[c1][piece],sq,0);
  2801.   pdir = &znextdir(ptype[c1][piece],sq,0);
  2802. #else
  2803.   ppos = nextpos[ptype[c1][piece]][sq];
  2804.   pdir = nextdir[ptype[c1][piece]][sq];
  2805. #endif /* __ZTC__ */
  2806.   if (piece == pawn)
  2807.     {
  2808.       u = ppos[sq];     /* follow no captures thread */
  2809.       if (color[u] == neutral)
  2810.         {
  2811.           if (atk1[u] >= atk2[u])
  2812.             return (false);
  2813.           if (atk2[u] < ctlP)
  2814.             {
  2815.               u = ppos[u];
  2816.               if (color[u] == neutral && atk1[u] >= atk2[u])
  2817.                 return (false);
  2818.             }
  2819.         }
  2820.       u = pdir[sq];     /* follow captures thread */
  2821.       if (color[u] == c2)
  2822.         return (false);
  2823.       u = pdir[u];
  2824.       if (color[u] == c2)
  2825.         return (false);
  2826.     }
  2827.   else
  2828.     {
  2829.       u = ppos[sq];
  2830.       do
  2831.         {
  2832.           if (color[u] != c1)
  2833.             if (atk2[u] == 0 || board[u] >= piece)
  2834.               return (false);
  2835.           u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2836.       } while (u != sq);
  2837.     }
  2838.   return (true);
  2839. }
  2840.  
  2841.  
  2842. static inline int
  2843. PawnValue (short int sq, short int side)
  2844.  
  2845. /*
  2846.   Calculate the positional value for a pawn on 'sq'.
  2847. */
  2848.  
  2849. {
  2850.   register short j, fyle, rank;
  2851.   register short s, a1, a2, in_square, r, e;
  2852.  
  2853.   a1 = (atk1[sq] & 0x4FFF);
  2854.   a2 = (atk2[sq] & 0x4FFF);
  2855.   rank = row (sq);
  2856.   fyle = column (sq);
  2857.   s = 0;
  2858.   if (c1 == white)
  2859.     {
  2860.       s = Mwpawn[sq];
  2861.       if ((sq == 11 && color[19] != neutral)
  2862.           || (sq == 12 && color[20] != neutral))
  2863.         s += PEDRNK2B;
  2864.       if ((fyle == 0 || PC1[fyle - 1] == 0)
  2865.           && (fyle == 7 || PC1[fyle + 1] == 0))
  2866.         s += ISOLANI[fyle];
  2867.       else if (PC1[fyle] > 1)
  2868.         s += PDOUBLED;
  2869.       if (a1 < ctlP && atk1[sq + 8] < ctlP)
  2870.         {
  2871.           s += BACKWARD[a2 & 0xFF];
  2872.           if (PC2[fyle] == 0)
  2873.             s += PWEAKH;
  2874.           if (color[sq + 8] != neutral)
  2875.             s += PBLOK;
  2876.         }
  2877.       if (PC2[fyle] == 0)
  2878.         {
  2879.           if (side == black)
  2880.             r = rank - 1;
  2881.           else
  2882.             r = rank;
  2883.           in_square = (row (bking) >= r && distance (sq, bking) < 8 - r);
  2884.           if (a2 == 0 || side == white)
  2885.             e = 0;
  2886.           else
  2887.             e = 1;
  2888.           for (j = sq + 8; j < 64; j += 8)
  2889.             if (atk2[j] >= ctlP)
  2890.               {
  2891.                 e = 2;
  2892.                 break;
  2893.               }
  2894.             else if (atk2[j] > 0 || color[j] != neutral)
  2895.               e = 1;
  2896.           if (e == 2)
  2897.             s += (stage * PassedPawn3[rank]) / 10;
  2898.           else if (in_square || e == 1)
  2899.             s += (stage * PassedPawn2[rank]) / 10;
  2900.           else if (emtl[black] > 0)
  2901.             s += (stage * PassedPawn1[rank]) / 10;
  2902.           else
  2903.             s += PassedPawn0[rank];
  2904.         }
  2905.     }
  2906.   else if (c1 == black)
  2907.     {
  2908.       s = Mbpawn[sq];
  2909.       if ((sq == 51 && color[43] != neutral)
  2910.           || (sq == 52 && color[44] != neutral))
  2911.         s += PEDRNK2B;
  2912.       if ((fyle == 0 || PC1[fyle - 1] == 0) &&
  2913.           (fyle == 7 || PC1[fyle + 1] == 0))
  2914.         s += ISOLANI[fyle];
  2915.       else if (PC1[fyle] > 1)
  2916.         s += PDOUBLED;
  2917.       if (a1 < ctlP && atk1[sq - 8] < ctlP)
  2918.         {
  2919.           s += BACKWARD[a2 & 0xFF];
  2920.           if (PC2[fyle] == 0)
  2921.             s += PWEAKH;
  2922.           if (color[sq - 8] != neutral)
  2923.             s += PBLOK;
  2924.         }
  2925.       if (PC2[fyle] == 0)
  2926.         {
  2927.           if (side == white)
  2928.             r = rank + 1;
  2929.           else
  2930.             r = rank;
  2931.           in_square = (row (wking) <= r && distance (sq, wking) < r + 1);
  2932.           if (a2 == 0 || side == black)
  2933.             e = 0;
  2934.           else
  2935.             e = 1;
  2936.           for (j = sq - 8; j >= 0; j -= 8)
  2937.             if (atk2[j] >= ctlP)
  2938.               {
  2939.                 e = 2;
  2940.                 break;
  2941.               }
  2942.             else if (atk2[j] > 0 || color[j] != neutral)
  2943.               e = 1;
  2944.           if (e == 2)
  2945.             s += (stage * PassedPawn3[7 - rank]) / 10;
  2946.           else if (in_square || e == 1)
  2947.             s += (stage * PassedPawn2[7 - rank]) / 10;
  2948.           else if (emtl[white] > 0)
  2949.             s += (stage * PassedPawn1[7 - rank]) / 10;
  2950.           else
  2951.             s += PassedPawn0[7 - rank];
  2952.         }
  2953.     }
  2954.   if (a2 > 0)
  2955.     {
  2956.       if (a1 == 0 || a2 > ctlP + 1)
  2957.         {
  2958.           s += HUNGP;
  2959.           ++hung[c1];
  2960.           if (trapped (sq))
  2961.             ++hung[c1];
  2962.         }
  2963.       else
  2964.         if (a2 > a1)
  2965.           s += ATAKD;
  2966.     }
  2967.   return (s);
  2968. }
  2969.  
  2970.  
  2971. static inline int
  2972. KnightValue (short int sq, short int side)
  2973.  
  2974. /*
  2975.   Calculate the positional value for a knight on 'sq'.
  2976. */
  2977.  
  2978. {
  2979.   register short s, a2, a1;
  2980.  
  2981.   s = Mknight[c1][sq];
  2982.   a2 = (atk2[sq] & 0x4FFF);
  2983.   if (a2 > 0)
  2984.     {
  2985.       a1 = (atk1[sq] & 0x4FFF);
  2986.       if (a1 == 0 || a2 > ctlBN + 1)
  2987.         {
  2988.           s += HUNGP;
  2989.           ++hung[c1];
  2990.           if (trapped (sq))
  2991.             ++hung[c1];
  2992.         }
  2993.       else
  2994.         if (a2 >= ctlBN || a1 < ctlP)
  2995.           s += ATAKD;
  2996.     }
  2997.   return (s);
  2998. }
  2999.  
  3000.  
  3001. static inline int
  3002. BishopValue (short int sq, short int side)
  3003.  
  3004. /*
  3005.   Calculate the positional value for a bishop on 'sq'.
  3006. */
  3007.  
  3008. {
  3009.   register short a2, a1;
  3010.   short s, mob;
  3011.  
  3012.   s = Mbishop[c1][sq];
  3013.   BRscan (sq, &s, &mob);
  3014.   s += BMBLTY[mob];
  3015.   a2 = (atk2[sq] & 0x4FFF);
  3016.   if (a2 > 0)
  3017.     {
  3018.       a1 = (atk1[sq] & 0x4FFF);
  3019.       if (a1 == 0 || a2 > ctlBN + 1)
  3020.         {
  3021.           s += HUNGP;
  3022.           ++hung[c1];
  3023.           if (trapped (sq))
  3024.             ++hung[c1];
  3025.         }
  3026.       else
  3027.         if (a2 >= ctlBN || a1 < ctlP)
  3028.           s += ATAKD;
  3029.     }
  3030.   return (s);
  3031. }
  3032.  
  3033.  
  3034. static inline int
  3035. RookValue (short int sq, short int side)
  3036.  
  3037. /*
  3038.   Calculate the positional value for a rook on 'sq'.
  3039. */
  3040.  
  3041. {
  3042.   register short fyle, a2, a1;
  3043.   short s, mob;
  3044.  
  3045.   s = RookBonus;
  3046.   BRscan (sq, &s, &mob);
  3047.   s += RMBLTY[mob];
  3048.   fyle = column (sq);
  3049.   if (PC1[fyle] == 0)
  3050.     s += RHOPN;
  3051.   if (PC2[fyle] == 0)
  3052.     s += RHOPNX;
  3053.   if (pmtl[c2] > 100 && row (sq) == rank7[c1])
  3054.     s += 10;
  3055.   if (stage > 2)
  3056.     s += 14 - taxicab (sq, EnemyKing);
  3057.   a2 = (atk2[sq] & 0x4FFF);
  3058.   if (a2 > 0)
  3059.     {
  3060.       a1 = (atk1[sq] & 0x4FFF);
  3061.       if (a1 == 0 || a2 > ctlR + 1)
  3062.         {
  3063.           s += HUNGP;
  3064.           ++hung[c1];
  3065.  
  3066.           if (trapped (sq))
  3067.             ++hung[c1];
  3068.         }
  3069.       else
  3070.         if (a2 >= ctlR || a1 < ctlP)
  3071.           s += ATAKD;
  3072.     }
  3073.   return (s);
  3074. }
  3075.  
  3076.  
  3077. static inline int
  3078. QueenValue (short int sq, short int side)
  3079.  
  3080. /*
  3081.   Calculate the positional value for a queen on 'sq'.
  3082. */
  3083.  
  3084. {
  3085.   register short s, a2, a1;
  3086.  
  3087.   s = (distance (sq, EnemyKing) < 3) ? 12 : 0;
  3088.   if (stage > 2)
  3089.     s += 14 - taxicab (sq, EnemyKing);
  3090.   a2 = (atk2[sq] & 0x4FFF);
  3091.   if (a2 > 0)
  3092.     {
  3093.       a1 = (atk1[sq] & 0x4FFF);
  3094.       if (a1 == 0 || a2 > ctlQ + 1)
  3095.         {
  3096.           s += HUNGP;
  3097.           ++hung[c1];
  3098.           if (trapped (sq))
  3099.             ++hung[c1];
  3100.         }
  3101.       else
  3102.         if (a2 >= ctlQ || a1 < ctlP)
  3103.           s += ATAKD;
  3104.     }
  3105.   return (s);
  3106. }
  3107.  
  3108.  
  3109. static inline int
  3110. KingValue (short int sq, short int side)
  3111.  
  3112. /*
  3113.   Calculate the positional value for a king on 'sq'.
  3114. */
  3115.  
  3116. {
  3117.   register short fyle, a2, a1;
  3118.   short s;
  3119.  
  3120.   s = Mking[c1][sq];
  3121.   if (KSFTY > 0)
  3122.     if (Developed[c2] || stage > 0)
  3123.       KingScan (sq, &s);
  3124.   if (castld[c1])
  3125.     s += KCASTLD;
  3126.   else if (Mvboard[kingP[c1]])
  3127.     s += KMOVD;
  3128.  
  3129.   fyle = column (sq);
  3130.   if (PC1[fyle] == 0)
  3131.     s += KHOPN;
  3132.   if (PC2[fyle] == 0)
  3133.     s += KHOPNX;
  3134.   switch (fyle)
  3135.     {
  3136.     case 5:
  3137.       if (PC1[7] == 0)
  3138.         s += KHOPN;
  3139.       if (PC2[7] == 0)
  3140.         s += KHOPNX;
  3141.       /* Fall through */
  3142.     case 4:
  3143.     case 6:
  3144.     case 0:
  3145.       if (PC1[fyle + 1] == 0)
  3146.         s += KHOPN;
  3147.       if (PC2[fyle + 1] == 0)
  3148.         s += KHOPNX;
  3149.       break;
  3150.     case 2:
  3151.       if (PC1[0] == 0)
  3152.         s += KHOPN;
  3153.       if (PC2[0] == 0)
  3154.         s += KHOPNX;
  3155.       /* Fall through */
  3156.     case 3:
  3157.     case 1:
  3158.     case 7:
  3159.       if (PC1[fyle - 1] == 0)
  3160.         s += KHOPN;
  3161.       if (PC2[fyle - 1] == 0)
  3162.         s += KHOPNX;
  3163.       break;
  3164.     default:
  3165.       /* Impossible! */
  3166.       break;
  3167.     }
  3168.  
  3169.   a2 = (atk2[sq] & 0x4FFF);
  3170.   if (a2 > 0)
  3171.     {
  3172.       a1 = (atk1[sq] & 0x4FFF);
  3173.       if (a1 == 0 || a2 > ctlK + 1)
  3174.         {
  3175.           s += HUNGP;
  3176.           ++hung[c1];
  3177.         }
  3178.       else
  3179.         s += ATAKD;
  3180.     }
  3181.   return (s);
  3182. }
  3183.  
  3184.  
  3185. void
  3186. ScorePosition (short int side, short int *score)
  3187.  
  3188. /*
  3189.   Perform normal static evaluation of board position. A score is generated
  3190.   for each piece and these are summed to get a score for each side.
  3191. */
  3192.  
  3193. {
  3194.   register short sq, s, i, xside;
  3195.   short pscore[2];
  3196.  
  3197.   UpdateWeights ();
  3198.   xside = otherside[side];
  3199.   pscore[white] = pscore[black] = 0;
  3200.  
  3201.   for (c1 = white; c1 <= black; c1++)
  3202.     {
  3203.       c2 = otherside[c1];
  3204.       atk1 = atak[c1];
  3205.       atk2 = atak[c2];
  3206.       PC1 = PawnCnt[c1];
  3207.       PC2 = PawnCnt[c2];
  3208.       for (i = PieceCnt[c1]; i >= 0; i--)
  3209.         {
  3210.           sq = PieceList[c1][i];
  3211.           switch (board[sq])
  3212.             {
  3213.             case pawn:
  3214.               s = PawnValue(sq, side);
  3215.               break;
  3216.             case knight:
  3217.               s = KnightValue(sq, side);
  3218.               break;
  3219.             case bishop:
  3220.               s = BishopValue(sq, side);
  3221.               break;
  3222.             case rook:
  3223.               s = RookValue(sq, side);
  3224.               break;
  3225.             case queen:
  3226.               s = QueenValue(sq, side);
  3227.               break;
  3228.             case king:
  3229.               s = KingValue(sq, side);
  3230.               break;
  3231.             default:
  3232.               s = 0;
  3233.               break;
  3234.             }
  3235.           pscore[c1] += s;
  3236.           svalue[sq] = s;
  3237.         }
  3238.     }
  3239.   if (hung[side] > 1)
  3240.     pscore[side] += HUNGX;
  3241.   if (hung[xside] > 1)
  3242.     pscore[xside] += HUNGX;
  3243.  
  3244.   *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
  3245.   if (dither)
  3246.     *score += urand () % dither;
  3247.  
  3248.   if (*score > 0 && pmtl[side] == 0)
  3249.     if (emtl[side] < valueR)
  3250.       *score = 0;
  3251.     else if (*score < valueR)
  3252.       *score /= 2;
  3253.   if (*score < 0 && pmtl[xside] == 0)
  3254.     if (emtl[xside] < valueR)
  3255.       *score = 0;
  3256.     else if (-*score < valueR)
  3257.       *score /= 2;
  3258.  
  3259.   if (mtl[xside] == valueK && emtl[side] > valueB)
  3260.     *score += 200;
  3261.   if (mtl[side] == valueK && emtl[xside] > valueB)
  3262.     *score -= 200;
  3263. }
  3264.  
  3265.  
  3266. static inline void
  3267. BlendBoard (const short int a[64], const short int b[64], short int c[64])
  3268. {
  3269.   register int sq;
  3270.  
  3271.   for (sq = 0; sq < 64; sq++)
  3272.     c[sq] = (a[sq] * (10 - stage) + b[sq] * stage) / 10;
  3273. }
  3274.  
  3275.  
  3276. static inline void
  3277. CopyBoard (const short int a[64], short int b[64])
  3278. {
  3279.   register int sq;
  3280.  
  3281.   for (sq = 0; sq < 64; sq++)
  3282.     b[sq] = a[sq];
  3283. }
  3284.  
  3285. void
  3286. ExaminePosition (void)
  3287.  
  3288. /*
  3289.   This is done one time before the search is started. Set up arrays
  3290.   Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the
  3291.   SqValue() function to determine the positional value of each piece.
  3292. */
  3293.  
  3294. {
  3295.   register short i, sq;
  3296.   short wpadv, bpadv, wstrong, bstrong, z, side, pp, j, k, val, Pd, fyle, rank;
  3297.   static short PawnStorm = false;
  3298.  
  3299.   ataks (white, atak[white]);
  3300.   ataks (black, atak[black]);
  3301.   UpdateWeights ();
  3302.   HasKnight[white] = HasKnight[black] = 0;
  3303.   HasBishop[white] = HasBishop[black] = 0;
  3304.   HasRook[white] = HasRook[black] = 0;
  3305.   HasQueen[white] = HasQueen[black] = 0;
  3306.   for (side = white; side <= black; side++)
  3307.     for (i = PieceCnt[side]; i >= 0; i--)
  3308.       switch (board[PieceList[side][i]])
  3309.         {
  3310.         case knight:
  3311.           ++HasKnight[side];
  3312.           break;
  3313.         case bishop:
  3314.           ++HasBishop[side];
  3315.           break;
  3316.         case rook:
  3317.           ++HasRook[side];
  3318.           break;
  3319.         case queen:
  3320.           ++HasQueen[side];
  3321.           break;
  3322.         }
  3323.   if (!Developed[white])
  3324.     Developed[white] = (board[1] != knight && board[2] != bishop &&
  3325.                         board[5] != bishop && board[6] != knight);
  3326.   if (!Developed[black])
  3327.     Developed[black] = (board[57] != knight && board[58] != bishop &&
  3328.                         board[61] != bishop && board[62] != knight);
  3329.   if (!PawnStorm && stage < 5)
  3330.     PawnStorm = ((column (wking) < 3 && column (bking) > 4) ||
  3331.                  (column (wking) > 4 && column (bking) < 3));
  3332.  
  3333.   CopyBoard (pknight, Mknight[white]);
  3334.   CopyBoard (pknight, Mknight[black]);
  3335.   CopyBoard (pbishop, Mbishop[white]);
  3336.   CopyBoard (pbishop, Mbishop[black]);
  3337.   BlendBoard (KingOpening, KingEnding, Mking[white]);
  3338.   BlendBoard (KingOpening, KingEnding, Mking[black]);
  3339.  
  3340.   for (sq = 0; sq < 64; sq++)
  3341.     {
  3342.       fyle = column (sq);
  3343.       rank = row (sq);
  3344.       wstrong = bstrong = true;
  3345.       for (i = sq; i < 64; i += 8)
  3346.         if (Patak (black, i))
  3347.           {
  3348.             wstrong = false;
  3349.             break;
  3350.           }
  3351.       for (i = sq; i >= 0; i -= 8)
  3352.         if (Patak (white, i))
  3353.           {
  3354.             bstrong = false;
  3355.             break;
  3356.           }
  3357.       wpadv = bpadv = PADVNCM;
  3358.       if ((fyle == 0 || PawnCnt[white][fyle - 1] == 0) &&
  3359.           (fyle == 7 || PawnCnt[white][fyle + 1] == 0))
  3360.         wpadv = PADVNCI;
  3361.       if ((fyle == 0 || PawnCnt[black][fyle - 1] == 0) &&
  3362.           (fyle == 7 || PawnCnt[black][fyle + 1] == 0))
  3363.         bpadv = PADVNCI;
  3364.       Mwpawn[sq] = (wpadv * PawnAdvance[sq]) / 10;
  3365.       Mbpawn[sq] = (bpadv * PawnAdvance[63 - sq]) / 10;
  3366.       Mwpawn[sq] += PawnBonus;
  3367.       Mbpawn[sq] += PawnBonus;
  3368.       if (Mvboard[kingP[white]])
  3369.         {
  3370.           if ((fyle < 3 || fyle > 4) && distance (sq, wking) < 3)
  3371.             Mwpawn[sq] += PAWNSHIELD;
  3372.         }
  3373.       else if (rank < 3 && (fyle < 2 || fyle > 5))
  3374.         Mwpawn[sq] += PAWNSHIELD / 2;
  3375.       if (Mvboard[kingP[black]])
  3376.         {
  3377.           if ((fyle < 3 || fyle > 4) && distance (sq, bking) < 3)
  3378.             Mbpawn[sq] += PAWNSHIELD;
  3379.         }
  3380.       else if (rank > 4 && (fyle < 2 || fyle > 5))
  3381.         Mbpawn[sq] += PAWNSHIELD / 2;
  3382.       if (PawnStorm)
  3383.         {
  3384.           if ((column (wking) < 4 && fyle > 4) ||
  3385.               (column (wking) > 3 && fyle < 3))
  3386.             Mwpawn[sq] += 3 * rank - 21;
  3387.           if ((column (bking) < 4 && fyle > 4) ||
  3388.               (column (bking) > 3 && fyle < 3))
  3389.             Mbpawn[sq] -= 3 * rank;
  3390.         }
  3391.       Mknight[white][sq] += 5 - distance (sq, bking);
  3392.       Mknight[white][sq] += 5 - distance (sq, wking);
  3393.       Mknight[black][sq] += 5 - distance (sq, wking);
  3394.       Mknight[black][sq] += 5 - distance (sq, bking);
  3395.       Mbishop[white][sq] += BishopBonus;
  3396.       Mbishop[black][sq] += BishopBonus;
  3397.       for (i = PieceCnt[black]; i >= 0; i--)
  3398.         if (distance (sq, PieceList[black][i]) < 3)
  3399.           Mknight[white][sq] += KNIGHTPOST;
  3400.       for (i = PieceCnt[white]; i >= 0; i--)
  3401.         if (distance (sq, PieceList[white][i]) < 3)
  3402.           Mknight[black][sq] += KNIGHTPOST;
  3403.       if (wstrong)
  3404.         Mknight[white][sq] += KNIGHTSTRONG;
  3405.       if (bstrong)
  3406.         Mknight[black][sq] += KNIGHTSTRONG;
  3407.       if (wstrong)
  3408.         Mbishop[white][sq] += BISHOPSTRONG;
  3409.       if (bstrong)
  3410.         Mbishop[black][sq] += BISHOPSTRONG;
  3411.  
  3412.       if (HasBishop[white] == 2)
  3413.         Mbishop[white][sq] += 8;
  3414.       if (HasBishop[black] == 2)
  3415.         Mbishop[black][sq] += 8;
  3416.       if (HasKnight[white] == 2)
  3417.         Mknight[white][sq] += 5;
  3418.       if (HasKnight[black] == 2)
  3419.         Mknight[black][sq] += 5;
  3420.  
  3421.       Kfield[white][sq] = Kfield[black][sq] = 0;
  3422.       if (distance (sq, wking) == 1)
  3423.         Kfield[black][sq] = KATAK;
  3424.       if (distance (sq, bking) == 1)
  3425.         Kfield[white][sq] = KATAK;
  3426.  
  3427.       Pd = 0;
  3428.       for (k = 0; k <= PieceCnt[white]; k++)
  3429.         {
  3430.           i = PieceList[white][k];
  3431.           if (board[i] == pawn)
  3432.             {
  3433.               pp = true;
  3434.               if (row (i) == 6)
  3435.                 z = i + 8;
  3436.               else
  3437.                 z = i + 16;
  3438.               for (j = i + 8; j < 64; j += 8)
  3439.                 if (Patak (black, j) || board[j] == pawn)
  3440.                   {
  3441.                     pp = false;
  3442.                     break;
  3443.                   }
  3444.               if (pp)
  3445.                 Pd += 5 * taxicab (sq, z);
  3446.               else
  3447.                 Pd += taxicab (sq, z);
  3448.             }
  3449.         }
  3450.       for (k = 0; k <= PieceCnt[black]; k++)
  3451.         {
  3452.           i = PieceList[black][k];
  3453.           if (board[i] == pawn)
  3454.             {
  3455.               pp = true;
  3456.               if (row (i) == 1)
  3457.                 z = i - 8;
  3458.               else
  3459.                 z = i - 16;
  3460.               for (j = i - 8; j >= 0; j -= 8)
  3461.                 if (Patak (white, j) || board[j] == pawn)
  3462.                   {
  3463.                     pp = false;
  3464.                     break;
  3465.                   }
  3466.               if (pp)
  3467.                 Pd += 5 * taxicab (sq, z);
  3468.               else
  3469.                 Pd += taxicab (sq, z);
  3470.             }
  3471.         }
  3472.       if (Pd != 0)
  3473.         {
  3474.           val = (Pd * stage2) / 10;
  3475.           Mking[white][sq] -= val;
  3476.           Mking[black][sq] -= val;
  3477.         }
  3478.     }
  3479. }
  3480.  
  3481. void
  3482. UpdateWeights (void)
  3483.  
  3484. /*
  3485.   If material balance has changed, determine the values for the positional
  3486.   evaluation terms.
  3487. */
  3488.  
  3489. {
  3490.   register short tmtl, s1;
  3491.  
  3492.   emtl[white] = mtl[white] - pmtl[white] - valueK;
  3493.   emtl[black] = mtl[black] - pmtl[black] - valueK;
  3494.   tmtl = emtl[white] + emtl[black];
  3495.   s1 = (tmtl > 6600) ? 0 : ((tmtl < 1400) ? 10 : (6600 - tmtl) / 520);
  3496.   if (s1 != stage)
  3497.     {
  3498.       stage = s1;
  3499.       stage2 = (tmtl > 3600) ? 0 : ((tmtl < 1400) ? 10 : (3600 - tmtl) / 220);
  3500.       PEDRNK2B = -15;   /* centre pawn on 2nd rank & blocked */
  3501.       PBLOK = -4;               /* blocked backward pawn */
  3502.       PDOUBLED = -14;   /* doubled pawn */
  3503.       PWEAKH = -4;              /* weak pawn on half open file */
  3504.       PAWNSHIELD = 10 - stage;  /* pawn near friendly king */
  3505.       PADVNCM = 10;             /* advanced pawn multiplier */
  3506.       PADVNCI = 7;              /* muliplier for isolated pawn */
  3507.       PawnBonus = stage;
  3508.  
  3509.       KNIGHTPOST = (stage + 2) / 3;     /* knight near enemy pieces */
  3510.       KNIGHTSTRONG = (stage + 6) / 2;   /* occupies pawn hole */
  3511.  
  3512.       BISHOPSTRONG = (stage + 6) / 2;   /* occupies pawn hole */
  3513.       BishopBonus = 2 * stage;
  3514.  
  3515.       RHOPN = 10;               /* rook on half open file */
  3516.       RHOPNX = 4;
  3517.       RookBonus = 6 * stage;
  3518.  
  3519.       XRAY = 8;         /* Xray attack on piece */
  3520.       PINVAL = 10;              /* Pin */
  3521.  
  3522.       KHOPN = (3 * stage - 30) / 2;     /* king on half open file */
  3523.       KHOPNX = KHOPN / 2;
  3524.       KCASTLD = 10 - stage;
  3525.       KMOVD = -40 / (stage + 1);        /* king moved before castling */
  3526.       KATAK = (10 - stage) / 2; /* B,R attacks near enemy king */
  3527.       if (stage < 8)
  3528.         KSFTY = 16 - 2 * stage;
  3529.       else
  3530.         KSFTY = 0;
  3531.  
  3532.       ATAKD = -6;               /* defender > attacker */
  3533.       HUNGP = -8;               /* each hung piece */
  3534.       HUNGX = -12;              /* extra for >1 hung piece */
  3535.     }
  3536. }
  3537.